Fix: Improve background service crash recovery#555
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Makes the existing safety net for the rare
ForegroundServiceDidNotStartInTimeExceptioncold-start crash more robust against edge cases. No visible difference in normal use — only matters when the safety net itself runs.Technical Context
App.kt(added in29df9062) usesLooper.loop()to keep the main thread alive after swallowing one occurrence of the timing exception. Three latent issues are fixed here.Looper.loop()was called regardless of which thread the throwable arrived on. The default uncaught handler can run on non-main threads, whereLooper.loop()itself would throw. Now guarded bythread === Looper.getMainLooper().thread.var foregroundExceptionHandledflag was a captured local with no synchronization. Replaced withAtomicBoolean.compareAndSet(false, true)so two concurrent throws can't both reach the suppression branch.log(...)orBugs.report(...)calls would escape and become its own uncaught exception. Both calls are now wrapped inrunCatching {}.super.onCreate(), and pre-creating the notification channel inMonitorControlbeforestartForegroundService(). The cold-start trace showsApplication.onCreate()completes before manifest receivers fire, so the handler is already installed before the 5-second timer can run out; channel creation is idempotent across app starts so pre-creating outsideMonitorService.onCreate()only helps first install.