feat: Auto-create traces for MAUI navigation events #5111
2 issues
find-bugs: Found 2 issues (2 medium)
Medium
Race condition: _currentTransaction field accessed without synchronization in singleton service - `src/Sentry.Maui/Internal/MauiEventsBinder.cs:19`
The _currentTransaction field is added to a singleton MauiEventsBinder and accessed from multiple event handlers (OnShellOnNavigating, OnApplicationOnModalPushed, OnApplicationOnModalPopped, OnWindowOnStopped) without thread synchronization. These handlers can fire concurrently from different navigation events. The StartNavigationTransaction method has a TOCTOU race where it checks _currentTransaction is { IsFinished: false } and then conditionally finishes or resets it - another thread could modify _currentTransaction between the check and the subsequent operations.
ChildSpanFinished can throw ObjectDisposedException due to race condition with Finish - `src/Sentry/TransactionTracer.cs:336`
The new ChildSpanFinished() method checks _hasFinished and then calls _idleTimer?.Start(), but the timer can be disposed by a concurrent Finish() call between these operations. This is the same race condition that ResetIdleTimeout() handles with a try-catch block, but ChildSpanFinished() lacks this protection. When SpanTracer.Finish() calls Transaction.ChildSpanFinished(), if TransactionTracer.Finish() is called concurrently, an unhandled ObjectDisposedException will propagate up to the caller.
Duration: 13m 41s · Tokens: 7.1M in / 74.0k out · Cost: $11.17 (+extraction: $0.01, +merge: $0.00)
Annotations
Check warning on line 19 in src/Sentry.Maui/Internal/MauiEventsBinder.cs
sentry-warden / warden: find-bugs
Race condition: _currentTransaction field accessed without synchronization in singleton service
The `_currentTransaction` field is added to a singleton `MauiEventsBinder` and accessed from multiple event handlers (`OnShellOnNavigating`, `OnApplicationOnModalPushed`, `OnApplicationOnModalPopped`, `OnWindowOnStopped`) without thread synchronization. These handlers can fire concurrently from different navigation events. The `StartNavigationTransaction` method has a TOCTOU race where it checks `_currentTransaction is { IsFinished: false }` and then conditionally finishes or resets it - another thread could modify `_currentTransaction` between the check and the subsequent operations.
Check warning on line 336 in src/Sentry/TransactionTracer.cs
sentry-warden / warden: find-bugs
ChildSpanFinished can throw ObjectDisposedException due to race condition with Finish
The new `ChildSpanFinished()` method checks `_hasFinished` and then calls `_idleTimer?.Start()`, but the timer can be disposed by a concurrent `Finish()` call between these operations. This is the same race condition that `ResetIdleTimeout()` handles with a try-catch block, but `ChildSpanFinished()` lacks this protection. When `SpanTracer.Finish()` calls `Transaction.ChildSpanFinished()`, if `TransactionTracer.Finish()` is called concurrently, an unhandled `ObjectDisposedException` will propagate up to the caller.