Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sentry-core/src/performance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ impl Transaction {
let sample_profile = inner.profiler_guard.take().and_then(|profiler_guard| {
profiling::finish_profiling(&transaction, profiler_guard, inner.context.trace_id)
});
drop(inner);

let mut envelope = protocol::Envelope::new();
envelope.add_item(transaction);
Expand Down
21 changes: 17 additions & 4 deletions sentry-core/src/scope/real.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,24 @@ impl fmt::Debug for ScopeGuard {
impl Drop for ScopeGuard {
fn drop(&mut self) {
if let Some((stack, depth)) = self.0.take() {
let mut stack = stack.write().unwrap_or_else(PoisonError::into_inner);
if stack.depth() != depth {
panic!("Tried to pop guards out of order");
let popped_depth = {
let mut stack = stack.write().unwrap_or_else(PoisonError::into_inner);
let popped_depth = stack.depth();
stack.pop();
popped_depth
};
// NOTE: We need to drop the `stack` lock before panicing, as the
// `PanicIntegration` will want to lock the `stack` itself
// (through `capture_event` -> `HubImpl::with`), and would thus
// result in a deadlock.
// Though that deadlock itself is detected by the `RwLock` (on macOS)
// and results in its own panic: `rwlock read lock would result in deadlock`.
// However that panic happens in the panic handler and will thus
// ultimately result in a `thread panicked while processing panic. aborting.`
// Long story short, we should not panic while holding the lock :-)
if popped_depth != depth {
panic!("Popped scope guard out of order");
}
stack.pop();
}
}
}
Expand Down
46 changes: 46 additions & 0 deletions sentry/tests/test_basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,49 @@ fn test_attachment_sent_from_scope() {
&& attachment.buffer == vec![1, 2, 3, 4, 5, 6, 7, 8, 9]
));
}

#[cfg(feature = "panic")]
#[test]
fn test_panic_scope_pop() {
let options = sentry::ClientOptions::new()
.add_integration(sentry::integrations::panic::PanicIntegration::new());

let events = sentry::test::with_captured_events_options(
|| {
// in case someone wants to log the original panics:
// let next = std::panic::take_hook();
// std::panic::set_hook(Box::new(move |info| {
// dbg!(&info);
// println!("{}", std::backtrace::Backtrace::force_capture());
// next(info);
// }));

let hub = sentry::Hub::current();
let scope1 = hub.push_scope();
let scope2 = hub.push_scope();

let panic = std::panic::catch_unwind(|| {
drop(scope1);
});
assert!(panic.is_err());

let panic = std::panic::catch_unwind(|| {
drop(scope2);
});
assert!(panic.is_err());
},
options,
);

assert_eq!(events.len(), 2);
assert_eq!(&events[0].exception[0].ty, "panic");
assert_eq!(
events[0].exception[0].value,
Some("Popped scope guard out of order".into())
);
assert_eq!(&events[1].exception[0].ty, "panic");
assert_eq!(
events[1].exception[0].value,
Some("Popped scope guard out of order".into())
);
}