Disk-persisted data can race during SDK re-init
還沒有人認領這個 Issue。
評估
研究方向
追蹤從 Sentry.init 到 Scopes.close(boolean) 的重新初始化流程,接著檢查 PersistingScopeObserver、CacheUtils、PersistingOptionsObserver 和 EnvelopeCache。首先聚焦於共用的 breadcrumbs.json QueueFile 以及舊 executor 的關閉行為;done 應證明重新初始化不會讓磁碟操作重疊,也不會遺失已持久化的 scope、options、session 或 envelope 資料。
由索引模型根據 Issue 內容生成。
描述
During SDK re-init (Sentry.init while already enabled), previous and new SDK lifecycles can concurrently read/write the same on-disk paths under cacheDirPath. On restart, Scopes.close(true) shuts the old executor down asynchronously rather than blocking, so old flush/session/envelope work can still touch files while the new init writes the same locations.
Impact: corrupted or lost scope/options/session state used for ANR/exit enrichment and crash recovery; possible lost breadcrumbs.
Why this races
- Re-init path closes previous scopes with
isRestarting=true, then continues init immediately:Sentry.init→Scopes.close(true) - On restart the old executor is closed via a submitted task (non-blocking), so pending disk work can still run briefly:
Scopes.close(boolean) - New init then enqueues session move/finalize, options observers, and scope-cache reset on the new executor against the same cache paths:
notifyOptionsObservers/movePreviousSession/finalizePreviousSession - Fixed filenames are not isolated per SDK lifecycle / run id
Disk-backed surfaces that share paths across re-init
Scope cache (.scope-cache/, via PersistingScopeObserver + CacheUtils):
breadcrumbs.json— singleQueueFile; old executor may still add/sync while new initresetCache()clears/syncs the same fileuser.json,tags.json,extras.json,contexts.json,request.json,level.json,fingerprint.json,transaction.json,trace.json,replay.json— plain overwrite/deleteof fixed names; no atomic replace- New init explicitly
resetCache()after options observers run, which collides with any late old-lifecycle flushes
Options cache (.options-cache/, via PersistingOptionsObserver and Android PersistingOptionsCacheGenerationObserver):
release.json,proguard-uuid.json,sdk-version.json,environment.json,dist.json,tags.json,replay-error-sample-rate.json,app-last-update-time.json- Written on every init via options observers; same fixed paths, non-atomic
FileOutputStreamoverwrite
Session / envelope cache (EnvelopeCache, Android AndroidEnvelopeCache):
session.json/previous_session.json— move + rewrite on session start; previous-session finalize also reads/deletes these*.envelopeoffline cache — old client flush vs new client store/send against same dir- crash markers:
last_crash,.sentry-native/last_crash,startup_crash(outbox) - Android ANR last-reported markers under cache dir
Other fixed-path / shared-dir writers (same cacheDirPath, lifecycle-overlapping on re-init):
- App-start profiling config file rewritten on init (
Sentry.handleAppStartProfilingConfig) - Profiling traces dir cleanup on init vs in-flight profile finalization
- Session Replay dirs (
replay_<id>/) under cache dir (ReplayCache); cleanup walks cache dir on integration start - ANR profile
QueueFiles under cache dir (AnrProfileManager/ rotation helper already documents concurrentQueueFilerisk)
Highest-confidence race today
Scope persistence breadcrumbs: single shared breadcrumbs.json QueueFile, old executor still draining adds while new init clears it in resetCache(), with only executor ordering (not cross-lifecycle isolation) as the safety net.
Related
- Closed perf work on scope persistence writes: https://github.com/getsentry/sentry-java/issues/5714
- Closed re-init executor timeout work: https://github.com/getsentry/sentry-java/issues/5715
- Closed “don’t wait when SDK is reinitialized”: https://github.com/getsentry/sentry-java/issues/3162
Unknowns
- Whether this has been observed in production beyond code inspection / reasoning about re-init
- How often customer/integration re-init hits the overlapping-executor window in practice
Raised by Markus Hintersteiner during SDK re-init / disk-persistence discussion.
Requested by markus.hintersteiner.
--
- 主要語言
- Kotlin
- 星號
- 1.4k
- 分支
- 478
- 平均合併
- 2 天 20 小時
- 30 天內合併 PR
- 71
貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
getsentry/sentry-java 的其他 Issue
-
Improvement Java Platform: Android Platform: Java
難度 2/5 1-3 小時 新手友好度 75/100
getsentry/sentry-java#6145 · 1 則留言 · 已指派 1 人 ·
-
Bug Java Platform: Android Platform: Java
難度 2/5 1-3 小時 新手友好度 78/100
getsentry/sentry-java#6138 · 1 則留言 ·
-
Feature Java Platform: Java Spans
難度 2/5 1-3 小時 新手友好度 68/100
getsentry/sentry-java#5984 · 1 則留言 ·
-
Android Task Traces
難度 2/5 1-3 小時 新手友好度 68/100
getsentry/sentry-java#5376 · 1 則留言 ·
-
Android Docs Errors
難度 2/5 1-3 小時 新手友好度 64/100
getsentry/sentry-java#5375 · 1 則留言 ·
查看 getsentry/sentry-java 的全部 Issue
相似的 Issue
-
autoteam community team/use
難度 2/5 1-3 小時 新手友好度 78/100
-
android: AlbumArtistDetailViewModel keeps groupKeys of albums that disappeared in expandedAlbums 未關閉task
難度 2/5 1-3 小時 新手友好度 70/100
-
難度 2/5 1-3 小時 新手友好度 90/100
aaif-goose/goose#12496 ·
-
Schema rejections are neither logged nor attributed, so the offending object cannot be identified 未關閉
難度 2/5 1-3 小時 新手友好度 75/100
zotero/zotero-android#350 ·
-
enhancement
難度 2/5 1-3 小時 新手友好度 75/100
Richie97/track-history#325 ·