diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e060eef42..a498f621f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ via the option `swizzleClassNameExclude`. - Speed up getBinaryImages (#4435) for finishing transactions and capturing events - Align SDK dispatch queue names (#4442) to start with `io.sentry` - Use UInts in envelope deserialization (#4441) +- Make `SentrySDK.replay.start()` thread safe (#4455) ## 8.38.0 diff --git a/Sources/Sentry/SentryReplayApi.m b/Sources/Sentry/SentryReplayApi.m index 3aad160229..d28c323ec3 100644 --- a/Sources/Sentry/SentryReplayApi.m +++ b/Sources/Sentry/SentryReplayApi.m @@ -3,6 +3,7 @@ #if SENTRY_TARGET_REPLAY_SUPPORTED # import "SentryHub+Private.h" +# import "SentryInternalCDefines.h" # import "SentryOptions+Private.h" # import "SentrySDK+Private.h" # import "SentrySessionReplayIntegration+Private.h" @@ -37,21 +38,30 @@ - (void)resume [replayIntegration resume]; } -- (void)start +- (void)start SENTRY_DISABLE_THREAD_SANITIZER("double-checked lock produce false alarms") { SentrySessionReplayIntegration *replayIntegration = (SentrySessionReplayIntegration *)[SentrySDK.currentHub getInstalledIntegration:SentrySessionReplayIntegration.class]; + // Start could be misused and called multiple times, causing it to + // be initialized more than once before being installed. + // Synchronizing it will prevent this problem. if (replayIntegration == nil) { - SentryOptions *currentOptions = SentrySDK.currentHub.client.options; - replayIntegration = - [[SentrySessionReplayIntegration alloc] initForManualUse:currentOptions]; + @synchronized(self) { + replayIntegration = (SentrySessionReplayIntegration *)[SentrySDK.currentHub + getInstalledIntegration:SentrySessionReplayIntegration.class]; + if (replayIntegration == nil) { + SentryOptions *currentOptions = SentrySDK.currentHub.client.options; + replayIntegration = + [[SentrySessionReplayIntegration alloc] initForManualUse:currentOptions]; - [SentrySDK.currentHub addInstalledIntegration:replayIntegration - name:NSStringFromClass(SentrySessionReplay.class)]; + [SentrySDK.currentHub + addInstalledIntegration:replayIntegration + name:NSStringFromClass(SentrySessionReplay.class)]; + } + } } - [replayIntegration start]; }