Commit 2e177685 by Abseil Team Committed by Copybara-Service

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
parent 9bff2a93
...@@ -199,6 +199,14 @@ T* SampleRecorder<T>::Register(Targs&&... args) { ...@@ -199,6 +199,14 @@ T* SampleRecorder<T>::Register(Targs&&... args) {
sample = new T(); sample = new T();
{ {
absl::MutexLock sample_lock(&sample->init_mu); 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)...); sample->PrepareForSampling(std::forward<Targs>(args)...);
} }
PushNew(sample); PushNew(sample);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment