diff --git a/CHANGELOG.md b/CHANGELOG.md index a869256072..7b6f0ea1ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ ### Fixes +- Fix thread safety in macOS NSException capture to prevent duplicate exception reports (#7672) - Capture transactions that finish during the launch profiling window instead of silently discarding them (#7602) - Capture instance and class method `[NSApplication _crashOnException]` exceptions (#7510) diff --git a/Sources/Sentry/SentryNSExceptionCaptureHelper.m b/Sources/Sentry/SentryNSExceptionCaptureHelper.m index 3530f3fccd..1cc717a9d9 100644 --- a/Sources/Sentry/SentryNSExceptionCaptureHelper.m +++ b/Sources/Sentry/SentryNSExceptionCaptureHelper.m @@ -5,20 +5,23 @@ # import "SentryCrash.h" # import "SentryNSExceptionCaptureHelper.h" # import "SentrySwift.h" +# import @implementation SentryNSExceptionCaptureHelper -static BOOL _insideReportException = NO; +// Thread-safe flag to prevent duplicate exception captures when +// _crashOnException: is called from within reportException: +static _Atomic BOOL _insideReportException = NO; + (void)reportException:(NSException *)exception { - _insideReportException = YES; + atomic_store(&_insideReportException, YES); [self captureException:exception]; } + (void)reportExceptionDidFinish { - _insideReportException = NO; + atomic_store(&_insideReportException, NO); } + (void)crashOnException:(NSException *)exception @@ -26,7 +29,7 @@ + (void)crashOnException:(NSException *)exception // When called from within reportException: (i.e., [super reportException:] internally // dispatches to _crashOnException: when NSApplicationCrashOnExceptions is YES), // the exception was already captured, so skip to avoid duplicate reports. - if (!_insideReportException) { + if (!atomic_load(&_insideReportException)) { [self captureException:exception]; } }