Skip to content

Commit 1c61ea6

Browse files
authored
Fix potential deadlock (#59)
## Motivation Some `Debug` implementations access a span's extensions, for example a `color_eyre` `Report` when printing a Spantrace. This can currently lead to a deadlock because `tracing-opentelemetry`'s tracing `Layer` holds an `extensions_mut()` guard for its Span while recording the event. ## Solution Move the the `OtelData` out of the span to not hold the lock and later write the extension back.
1 parent 5223a67 commit 1c61ea6

File tree

1 file changed

+8
-5
lines changed

1 file changed

+8
-5
lines changed

src/layer.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -835,10 +835,9 @@ where
835835
#[cfg(not(feature = "tracing-log"))]
836836
let target = target.string(meta.target());
837837

838-
let mut extensions = span.extensions_mut();
839-
let span_builder = extensions
840-
.get_mut::<OtelData>()
841-
.map(|data| &mut data.builder);
838+
// Move out extension data to not hold the extensions lock across the event.record() call, which could result in a deadlock
839+
let mut otel_data = span.extensions_mut().remove::<OtelData>();
840+
let span_builder = otel_data.as_mut().map(|data| &mut data.builder);
842841

843842
let mut otel_event = otel::Event::new(
844843
String::new(),
@@ -852,7 +851,9 @@ where
852851
exception_config: self.exception_config,
853852
});
854853

855-
if let Some(OtelData { builder, .. }) = extensions.get_mut::<OtelData>() {
854+
if let Some(mut otel_data) = otel_data {
855+
let builder = &mut otel_data.builder;
856+
856857
if builder.status == otel::Status::Unset
857858
&& *meta.level() == tracing_core::Level::ERROR
858859
{
@@ -895,6 +896,8 @@ where
895896
} else {
896897
builder.events = Some(vec![otel_event]);
897898
}
899+
900+
span.extensions_mut().replace(otel_data);
898901
}
899902
};
900903
}

0 commit comments

Comments
 (0)