Repository navigation
[iOS] Stop RCTIdentifierPool::dequeue from spinning forever when the pool is full - #58947
Open
kimseongchan0914 wants to merge 1 commit into
Open
kimseongchan0914 wants to merge 1 commit into
kimseongchan0914 wants to merge 1 commit into
Conversation
…s full dequeue() scanned for a free identifier in an unbounded loop. Once every identifier was taken, which happens when the touch handlers leak them over a long-lived process, the loop never exited and hung the main thread. Bound the scan to one pass over the pool. If no identifier is free, reclaim them all and reuse one. Also initialise lastIndex, which was read before being assigned. Fixes react#58441 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Summary:
Fixes #58441.
RCTIdentifierPool::dequeue()looks for a free identifier in an unboundedwhile (true)loop. When every identifier is taken, the loop never exits.RCTSurfaceTouchHandlerandRCTSurfacePointerHandlercall it on the main thread fromtouchesBegan:, so the app hangs at 100% CPU until the watchdog kills it (0x8BADF00D). The issue has a symbolicated production hang report.The pool fills up when identifiers leak over a long-lived process, for example when a touch is missing from the local registry at unregister time.
This change:
sizestepslastIndexis back where it started, so scanning further can't find anything new.lastIndex, which was read as astd::bitsetsubscript before being assigned.Whenever the old code terminated, the new code returns the same identifiers. This PR does not fix the identifier leak itself. It only stops a leak from turning into a hang. I'm happy to change what happens on exhaustion if you prefer a different policy.
Changelog:
[IOS] [FIXED] - Fix main thread hang in the touch handler when all touch identifiers are in use
Test Plan:
The bug reproduces against the header alone, so I tested it with standalone programs built with
clang++ -std=c++20.1. Full pool. Fill all 17 slots (the size both handlers use), then call
dequeue()again:16, and the next call returns02. Same behaviour when the pool is not full. Ran the old and new headers side by side over 2,000 random dequeue/enqueue sequences of 200 operations each, never exhausting the pool, with the old
lastIndexpinned to 0:3. Formatting.
clang-formatwith the repo's ObjC style reports no diff for the file.Not run:
yarn format-check-cpp, an iOS build, and an on-device check. The C++ API snapshots are unaffected because no public member changed.🤖 Generated with Claude Code