Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions centipede/rusage_profiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ const RUsageProfiler::Snapshot& RUsageProfiler::TakeSnapshot( //
return kEmpty;
}

absl::WriterMutexLock lock{mutex_};
absl::WriterMutexLock lock{snapshots_mutex_};

RUsageTiming snap_timing = RUsageTiming::Zero();
RUsageTiming delta_timing = RUsageTiming::Zero();
Expand Down Expand Up @@ -420,7 +420,7 @@ void RUsageProfiler::StartTimelapse( //
absl::Duration interval, //
bool also_log, //
std::string title) {
absl::WriterMutexLock lock{mutex_};
absl::WriterMutexLock lock{recorder_mutex_};
FUZZTEST_CHECK(!timelapse_recorder_) << "StopTimelapse() wasn't called";
timelapse_recorder_ = std::make_unique<PeriodicAction>(
[this, loc = std::move(loc), title = std::move(title), also_log]() {
Expand All @@ -431,7 +431,7 @@ void RUsageProfiler::StartTimelapse( //
}

void RUsageProfiler::StopTimelapse() {
absl::WriterMutexLock lock{mutex_};
absl::WriterMutexLock lock{recorder_mutex_};
FUZZTEST_CHECK(timelapse_recorder_) << "StartTimelapse() wasn't called";
timelapse_recorder_.reset();
}
Expand Down Expand Up @@ -483,7 +483,7 @@ void RUsageProfiler::PrintReport( //

void RUsageProfiler::GenerateReport(
ReportSink* absl_nonnull report_sink) const {
absl::ReaderMutexLock lock{mutex_};
absl::ReaderMutexLock lock{snapshots_mutex_};
// Prevent interleaved reports from multiple concurrent RUsageProfilers.
ABSL_CONST_INIT static absl::Mutex report_generation_mutex_{absl::kConstInit};
absl::WriterMutexLock logging_lock{report_generation_mutex_};
Expand Down
10 changes: 6 additions & 4 deletions centipede/rusage_profiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,17 +427,19 @@ class RUsageProfiler {
// The sequential ID of this profiler. Used to annotate all log
const int id_;

// Mutex for the mutable data further below.
mutable absl::Mutex mutex_;
// Mutexes for the mutable data further below.
mutable absl::Mutex snapshots_mutex_;
mutable absl::Mutex recorder_mutex_;

// Chronological snapshots. Using std::deque gives a better-than-vector
// average insertion speed, preserves iterators across insertions, and strikes
// a balance between vector's and list's additional storage.
std::deque<Snapshot> snapshots_ ABSL_GUARDED_BY(mutex_);
std::deque<Snapshot> snapshots_ ABSL_GUARDED_BY(snapshots_mutex_);
// A temporarily lived periodic action that records and optionally logs
// timelapse snapshots. (Re)created by each new call to StartTimelapse() and
// terminated by StopTimelapse() or the dtor, whichever comes first.
std::unique_ptr<PeriodicAction> timelapse_recorder_ ABSL_GUARDED_BY(mutex_);
std::unique_ptr<PeriodicAction> timelapse_recorder_
ABSL_GUARDED_BY(recorder_mutex_);

// An auto-starting timer passed to RUsageTiming::Snapshot() in order to track
// this RUsageProfiler object's lifetime stats rather than the process's
Expand Down
20 changes: 20 additions & 0 deletions centipede/rusage_profiler_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,24 @@ TEST(RUsageProfilerTest, ValidateReport) {
rprof.GenerateReport(&report_capture);
}

TEST(RUsageProfilerTest, DeadlockReproduction) {
const auto rusage_scope = RUsageScope::ThisProcess();
for (int i = 0; i < 1000; ++i) {
RUsageProfiler rprof{rusage_scope,
RUsageProfiler::kAllMetrics,
RUsageProfiler::kRaiiOff,
{__FILE__, __LINE__}};
// Use a tiny interval to trigger frequent snapshots
rprof.StartTimelapse({__FILE__, __LINE__}, absl::Microseconds(10),
/*also_log=*/false, "Timelapse");

// Briefly wait to ensure the background thread starts running
absl::SleepFor(absl::Microseconds(10));

// This call frequently deadlocks because it holds the mutex while
// waiting for the background thread to finish its TakeSnapshot() call.
rprof.StopTimelapse();
}
}

} // namespace fuzztest::internal
Loading