fix: serialize backgroundTimeRemaining with cancellation check#667
Merged
nickolas-dimitrakas merged 5 commits intomainfrom Mar 17, 2026
Merged
fix: serialize backgroundTimeRemaining with cancellation check#667nickolas-dimitrakas merged 5 commits intomainfrom
nickolas-dimitrakas merged 5 commits intomainfrom
Conversation
📦 SDK Size Impact ReportMeasures how much the SDK adds to an app's size (with-SDK minus without-SDK).
➡️ SDK size impact change is minimal. Raw measurementsTarget branch (main): {"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":1944,"with_sdk_executable_size_bytes":76360,"sdk_impact_kb":1860,"sdk_executable_impact_bytes":896,"xcframework_size_kb":9720}This PR: {"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":1944,"with_sdk_executable_size_bytes":76360,"sdk_impact_kb":1860,"sdk_executable_impact_bytes":896,"xcframework_size_kb":9716} |
Add regression test that asserts all backgroundTimeRemaining calls happen on the main thread via dispatch_sync, preventing XPC race conditions during app suspension that caused heap corruption crashes. Made-with: Cursor
This reverts commit fef0060.
jamesnrokt
reviewed
Mar 16, 2026
Eliminates ARC TOCTOU race between nil check and .isCancelled access. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jamesnrokt
approved these changes
Mar 16, 2026
BrandonStalnaker
approved these changes
Mar 17, 2026
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.
Background
beginBackgroundTimeCheckLoopon iOS 26's hardened xzone allocator (EXC_BREAKPOINTin_xzm_xzone_malloc_freelist_outlined).isCancelledcheck and thebackgroundTimeRemainingcall ran on a worker thread, while the expiration handler and foreground handler cancelled the operation and ended the background task on the main thread. In the ~2ms gap between the check and the call, iOS could tear down the underlying XPC objects (RBSProcessHandle,RBSConnection), causingbackgroundTimeRemainingto access freed memory.What Has Changed
isCancelledcheck andbackgroundTimeRemainingcall are now performed together inside a singledispatch_sync(dispatch_get_main_queue())block. This serializes them with the expiration handler and foreground handler (both fire on the main thread), making it impossible for the background task to be torn down between the check and the call.testForegroundHandlerStopsBackgroundTimeRemainingCallsunit test covering the foreground handler cancellation path — the exact scenario where the race was observed in production.Checklist
Additional Notes
xzone_malloc) that catches use-after-free asEXC_BREAKPOINTrather than silently corrupting memory. The same race existed on older iOS versions but was masked by the permissive allocator.Reported crash 1
Reported crash 2
Reference Issue (For employees only. Ignore if you are an outside contributor)