summaryrefslogtreecommitdiff
path: root/absl/profiling/internal
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2022-12-08 08:25:41 -0800
committerGravatar Copybara-Service <copybara-worker@google.com>2022-12-08 08:26:40 -0800
commit2e17768541d7caa0da88e774f916b012ffc57ebb (patch)
treedbf6a1d6f2ad07c60de013696e3bedc0c9afb83f /absl/profiling/internal
parent9bff2a9302a8dbf91712fc215eb2e2cf8ec234e7 (diff)
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
Diffstat (limited to 'absl/profiling/internal')
-rw-r--r--absl/profiling/internal/sample_recorder.h8
1 files changed, 8 insertions, 0 deletions
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<T>::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<Targs>(args)...);
}
PushNew(sample);