-
Notifications
You must be signed in to change notification settings - Fork 127
Fix deadlock if steady_clock::now() returns the same value twice #132
Conversation
`Span::isFinished()` returns true iff the span's duration is zero. So, if `steady_clock::now()` returns the same value at span creation as at `Finish()` (unlikely, but possible, especially in virtualized environments), the following scenario can happen: - `Span::FinishWithOptions` sets `_duration` to zero - and then calls `reportSpan`, which calls `RemoteReporter::report` - which acquires the reporter mutex and - adds the span to the reporter's `_queue` Later: - `RemoteReporter::sweepQueue` acquires the reporter mutex - `RemoteReporter::sweepQueue` makes a copy of the span (https://github.com/jaegertracing/jaeger-client-cpp/blob/7e9a135b362c47f7e4d42e0693b05b91a70e6888/src/jaegertracing/reporters/RemoteReporter.cpp#L95) - The span is serialized in `RemoteReporter::sendSpan` - The span (the copy made above) needs to be destroyed because the block in `sweepQueue` ends. - The span's destructor is called, which calls `FinishWithOptions` again - ... which sees that `_duration` is zero, so `isFinished()` returns false: https://github.com/jaegertracing/jaeger-client-cpp/blob/7e9a135b362c47f7e4d42e0693b05b91a70e6888/src/jaegertracing/Span.cpp#L94 - so it tries to call `reportSpan` again - which tries to acquire the reporter's mutex - but we're holding the lock in `sweepQueue`, so - deadlock. Relevant stack trace: ``` (gdb) bt (gdb) bt #0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135 jaegertracing#1 0x00007fb09c722023 in __GI___pthread_mutex_lock (mutex=0x7fb088b1c1c0) at ../nptl/pthread_mutex_lock.c:78 jaegertracing#2 0x00007fb08860987b in jaegertracing::reporters::RemoteReporter::report(jaegertracing::Span const&) () from /usr/local/lib/libjaegertracing_plugin.so jaegertracing#3 0x00007fb0885b6506 in jaegertracing::Span::FinishWithOptions(opentracing::v2::FinishSpanOptions const&) [clone .localalias.361] () from /usr/local/lib/libjaegertracing_plugin.so jaegertracing#4 0x00007fb08860849a in jaegertracing::Span::~Span() [clone .constprop.253] () from /usr/local/lib/libjaegertracing_plugin.so jaegertracing#5 0x00007fb08860a8fa in jaegertracing::reporters::RemoteReporter::sweepQueue() () from /usr/local/lib/libjaegertracing_plugin.so jaegertracing#6 0x00007fb0886f2f5f in execute_native_thread_routine () from /usr/local/lib/libjaegertracing_plugin.so jaegertracing#7 0x00007fb09c71f6db in start_thread (arg=0x7fb087574700) at pthread_create.c:463 jaegertracing#8 0x00007fb0989ae88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 ``` Fixed by enforcing a minimum span duration of 1 `SteadyClock` tick. Signed-off-by: Tudor Bosman <tudor@rockset.com>
CI fails in the same way as #130. That test is flaky.
|
#127 has to do with destroying the These are two separate issues. |
src/jaegertracing/Span.cpp
Outdated
@@ -96,6 +96,12 @@ void Span::FinishWithOptions( | |||
return; | |||
} | |||
_duration = finishTimeSteady - _startTimeSteady; | |||
if (_duration <= SteadyClock::duration()) { | |||
// Enfoce minimum duration of 1 tick (1ns on Linux), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for nit, but typo Enforce
.
Fixed the typo. PTAL? |
Thanks! Are you planning to cut a new release any time soon? (I'm okay using the master branch as well, just curious.) |
I won't stop you if you'd like to release a minor version. See RELEASE.md for how to do it. I can build the plugin or do the entire release, but I'd like to see others take a stab at it. |
Span::isFinished()
returns true iff the span's duration is zero. So, ifsteady_clock::now()
returns the same value at span creation as atFinish()
(unlikely, but possible, especially in virtualized environments), the following scenario can happen:Span::FinishWithOptions
sets_duration
to zeroreportSpan
, which callsRemoteReporter::report
_queue
Later:
RemoteReporter::sweepQueue
acquires the reporter mutexRemoteReporter::sweepQueue
makes a copy of the span:jaeger-client-cpp/src/jaegertracing/reporters/RemoteReporter.cpp
Line 95 in 7e9a135
RemoteReporter::sendSpan
sweepQueue
ends.FinishWithOptions
again_duration
is zero, soisFinished()
returns false:jaeger-client-cpp/src/jaegertracing/Span.cpp
Line 94 in 7e9a135
reportSpan
againsweepQueue
, soRelevant stack trace:
Fixed by enforcing a minimum span duration of 1
SteadyClock
tick.Signed-off-by: Tudor Bosman tudor@rockset.com
Which problem is this PR solving?
Short description of the changes