From 2e17768541d7caa0da88e774f916b012ffc57ebb Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 8 Dec 2022 08:25:41 -0800 Subject: The abridged justification is as follows: - The deadlock seems to occur if flag initialization happens to occur while a sample is being created. - Each sample has its own mutex that is locked when a new sample is registered, i.e. created for the first time. - The flag implicitly creates a global sampler object which locks `graveyard_`'s mutex. - Usually, in `PushDead`, the `graveyard` is locked before the sample, hence triggering deadlock detection. - This lock order can never be recreated since this code is executed exactly once per sample object, and the sample object cannot be accessed until after the method returns. - It should therefore be safe to ignore any locking order condition that may occur during sample creation. PiperOrigin-RevId: 493901903 Change-Id: I094abca82c1a8a82ac392383c72469d68eef09c4 --- absl/profiling/internal/sample_recorder.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'absl') diff --git a/absl/profiling/internal/sample_recorder.h b/absl/profiling/internal/sample_recorder.h index ef1489b1..371f6c47 100644 --- a/absl/profiling/internal/sample_recorder.h +++ b/absl/profiling/internal/sample_recorder.h @@ -199,6 +199,14 @@ T* SampleRecorder::Register(Targs&&... args) { sample = new T(); { absl::MutexLock sample_lock(&sample->init_mu); + // If flag initialization happens to occur (perhaps in another thread) + // while in this block, it will lock `graveyard_` which is usually always + // locked before any sample. This will appear as a lock inversion. + // However, this code is run exactly once per sample, and this sample + // cannot be accessed until after it is returned from this method. This + // means that this lock state can never be recreated, so we can safely + // inform the deadlock detector to ignore it. + sample->init_mu.ForgetDeadlockInfo(); sample->PrepareForSampling(std::forward(args)...); } PushNew(sample); -- cgit v1.2.3