Skip to content

Commit 509e0e3

Browse files
committed
fix: replay integration race condition when configuration changes while the replay is starting
1 parent b03eb7f commit 509e0e3

File tree

1 file changed

+32
-26
lines changed

1 file changed

+32
-26
lines changed

sentry-android-replay/src/main/java/io/sentry/android/replay/ReplayIntegration.kt

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -158,22 +158,24 @@ public class ReplayIntegration(
158158
return
159159
}
160160

161-
val isFullSession = random.sample(options.experimental.sessionReplay.sessionSampleRate)
162-
if (!isFullSession && !options.experimental.sessionReplay.isSessionReplayForErrorsEnabled) {
163-
options.logger.log(INFO, "Session replay is not started, full session was not sampled and onErrorSampleRate is not specified")
164-
return
165-
}
161+
synchronized (this) {
162+
val isFullSession = random.sample(options.experimental.sessionReplay.sessionSampleRate)
163+
if (!isFullSession && !options.experimental.sessionReplay.isSessionReplayForErrorsEnabled) {
164+
options.logger.log(INFO, "Session replay is not started, full session was not sampled and onErrorSampleRate is not specified")
165+
return
166+
}
166167

167-
recorderConfig = recorderConfigProvider?.invoke(false) ?: ScreenshotRecorderConfig.from(context, options.experimental.sessionReplay)
168-
captureStrategy = replayCaptureStrategyProvider?.invoke(isFullSession) ?: if (isFullSession) {
169-
SessionCaptureStrategy(options, hub, dateProvider, replayCacheProvider = replayCacheProvider)
170-
} else {
171-
BufferCaptureStrategy(options, hub, dateProvider, random, replayCacheProvider = replayCacheProvider)
172-
}
168+
recorderConfig = recorderConfigProvider?.invoke(false) ?: ScreenshotRecorderConfig.from(context, options.experimental.sessionReplay)
169+
captureStrategy = replayCaptureStrategyProvider?.invoke(isFullSession) ?: if (isFullSession) {
170+
SessionCaptureStrategy(options, hub, dateProvider, replayCacheProvider = replayCacheProvider)
171+
} else {
172+
BufferCaptureStrategy(options, hub, dateProvider, random, replayCacheProvider = replayCacheProvider)
173+
}
173174

174-
captureStrategy?.start(recorderConfig)
175-
recorder?.start(recorderConfig)
176-
registerRootViewListeners()
175+
captureStrategy?.start(recorderConfig)
176+
recorder?.start(recorderConfig)
177+
registerRootViewListeners()
178+
}
177179
}
178180

179181
override fun resume() {
@@ -224,13 +226,15 @@ public class ReplayIntegration(
224226
return
225227
}
226228

227-
unregisterRootViewListeners()
228-
recorder?.stop()
229-
gestureRecorder?.stop()
230-
captureStrategy?.stop()
231-
isRecording.set(false)
232-
captureStrategy?.close()
233-
captureStrategy = null
229+
synchronized (this) {
230+
unregisterRootViewListeners()
231+
recorder?.stop()
232+
gestureRecorder?.stop()
233+
captureStrategy?.stop()
234+
isRecording.set(false)
235+
captureStrategy?.close()
236+
captureStrategy = null
237+
}
234238
}
235239

236240
override fun onScreenshotRecorded(bitmap: Bitmap) {
@@ -270,13 +274,15 @@ public class ReplayIntegration(
270274
return
271275
}
272276

273-
recorder?.stop()
277+
synchronized (this) {
278+
recorder?.stop()
274279

275-
// refresh config based on new device configuration
276-
recorderConfig = recorderConfigProvider?.invoke(true) ?: ScreenshotRecorderConfig.from(context, options.experimental.sessionReplay)
277-
captureStrategy?.onConfigurationChanged(recorderConfig)
280+
// refresh config based on new device configuration
281+
recorderConfig = recorderConfigProvider?.invoke(true) ?: ScreenshotRecorderConfig.from(context, options.experimental.sessionReplay)
282+
captureStrategy?.onConfigurationChanged(recorderConfig)
278283

279-
recorder?.start(recorderConfig)
284+
recorder?.start(recorderConfig)
285+
}
280286
}
281287

282288
override fun onConnectionStatusChanged(status: ConnectionStatus) {

0 commit comments

Comments
 (0)