Commit d061260
fix: guard executor shutdown in BaseCaptureStrategy.stop() (#5627)
* fix: guard executor shutdown in BaseCaptureStrategy.stop()
Each start/stop cycle leaked one SentryReplayPersister-* thread because
stop() reset delegated properties (segmentTimestamp, currentReplayId)
whose setters dispatch to persistingExecutor, initialising the lazy —
but stop() never shut it down.
Replace the lazy delegate with an explicit nullable holder so the
executor is only created when actually needed and can be detected at
stop() time. Call shutdownNow() (non-blocking) rather than the blocking
shutdown() to avoid ANRs when stop() runs on the main thread.
Fixes #5564
* style: apply spotless formatting
* refactor(replay): move persistingExecutor ownership to ReplayIntegration
Move persistingExecutor out of BaseCaptureStrategy and into
ReplayIntegration, passing it as a constructor argument to CaptureStrategy
subclasses. Shut it down in ReplayIntegration.close() alongside
replayExecutor so executor lifecycle is managed in one place.
* Fix leak in ReplayIntegration due to persisting executor not being shut down
Add the persistingExecutor argument to SessionCaptureStrategy and
BufferCaptureStrategy constructor calls in tests, and add changelog entry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Remove stray merge conflict marker from CHANGELOG.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Remove no-op leak test from SessionCaptureStrategyTest
The test used a mocked executor that never spawned threads, so the
thread-count assertion was always true regardless of the fix.
The executor lifecycle is now owned by ReplayIntegration, not
SessionCaptureStrategy, so the test belonged at the wrong layer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add executor leak regression test to ReplayIntegrationTest
Uses real ScheduledThreadPoolExecutor threads so the test actually
fails if the shutdown in close() is removed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Use shutdownNow() for replay executors in close() to avoid ANR
shutdown() calls awaitTermination() which blocks up to
shutdownTimeoutMillis. Since close() can run on the main thread
(via Sentry.close() from hybrid SDKs), this risks an ANR.
shutdownNow() is non-blocking and sufficient at teardown.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 58b65f0 commit d061260
9 files changed
Lines changed: 101 additions & 23 deletions
File tree
- sentry-android-replay/src
- main/java/io/sentry/android/replay
- capture
- util
- test/java/io/sentry/android/replay
- capture
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
Lines changed: 34 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
110 | | - | |
| 110 | + | |
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
114 | 121 | | |
115 | 122 | | |
116 | 123 | | |
| |||
192 | 199 | | |
193 | 200 | | |
194 | 201 | | |
| 202 | + | |
195 | 203 | | |
196 | 204 | | |
197 | 205 | | |
| |||
201 | 209 | | |
202 | 210 | | |
203 | 211 | | |
| 212 | + | |
204 | 213 | | |
205 | 214 | | |
206 | 215 | | |
| |||
373 | 382 | | |
374 | 383 | | |
375 | 384 | | |
376 | | - | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
377 | 399 | | |
378 | 400 | | |
379 | 401 | | |
| |||
554 | 576 | | |
555 | 577 | | |
556 | 578 | | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
557 | 589 | | |
Lines changed: 1 addition & 18 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
29 | 28 | | |
30 | 29 | | |
31 | 30 | | |
| |||
34 | 33 | | |
35 | 34 | | |
36 | 35 | | |
37 | | - | |
38 | 36 | | |
39 | | - | |
40 | 37 | | |
41 | 38 | | |
42 | 39 | | |
| |||
50 | 47 | | |
51 | 48 | | |
52 | 49 | | |
| 50 | + | |
53 | 51 | | |
54 | 52 | | |
55 | 53 | | |
| |||
58 | 56 | | |
59 | 57 | | |
60 | 58 | | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | 59 | | |
67 | 60 | | |
68 | 61 | | |
| |||
192 | 185 | | |
193 | 186 | | |
194 | 187 | | |
195 | | - | |
196 | | - | |
197 | | - | |
198 | | - | |
199 | | - | |
200 | | - | |
201 | | - | |
202 | | - | |
203 | | - | |
204 | | - | |
205 | 188 | | |
206 | 189 | | |
207 | 190 | | |
| |||
Lines changed: 6 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
36 | 37 | | |
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
| 44 | + | |
43 | 45 | | |
44 | 46 | | |
45 | 47 | | |
| |||
150 | 152 | | |
151 | 153 | | |
152 | 154 | | |
153 | | - | |
154 | | - | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
155 | 159 | | |
156 | 160 | | |
157 | 161 | | |
| |||
Lines changed: 10 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
24 | 25 | | |
25 | | - | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
26 | 35 | | |
27 | 36 | | |
28 | 37 | | |
| |||
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
60 | 68 | | |
61 | 69 | | |
62 | 70 | | |
Lines changed: 27 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
754 | 754 | | |
755 | 755 | | |
756 | 756 | | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
757 | 763 | | |
758 | 764 | | |
759 | 765 | | |
| |||
1104 | 1110 | | |
1105 | 1111 | | |
1106 | 1112 | | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |
| 1126 | + | |
1107 | 1127 | | |
1108 | 1128 | | |
1109 | 1129 | | |
| |||
1116 | 1136 | | |
1117 | 1137 | | |
1118 | 1138 | | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + | |
1119 | 1146 | | |
1120 | 1147 | | |
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
114 | 120 | | |
115 | 121 | | |
116 | 122 | | |
| |||
sentry-android-replay/src/test/java/io/sentry/android/replay/capture/SessionCaptureStrategyTest.kt
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
122 | 122 | | |
123 | 123 | | |
124 | 124 | | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
125 | 133 | | |
126 | 134 | | |
127 | 135 | | |
| |||
0 commit comments