From b4544bbb3c778f888eca62da96f9be92e45e8d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=84=B1=EC=B0=AC?= <265934944+kimseongchan0914@users.noreply.github.com> Date: Thu, 8 Oct 2026 19:45:13 +0900 Subject: [PATCH] Stop RCTIdentifierPool::dequeue from spinning forever when the pool is 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 #58441 Co-Authored-By: Claude Opus 5.5 --- .../React/Fabric/Utils/RCTIdentifierPool.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/react-native/React/Fabric/Utils/RCTIdentifierPool.h b/packages/react-native/React/Fabric/Utils/RCTIdentifierPool.h index ec5e849c8127..8d92b3dcc922 100644 --- a/packages/react-native/React/Fabric/Utils/RCTIdentifierPool.h +++ b/packages/react-native/React/Fabric/Utils/RCTIdentifierPool.h @@ -21,13 +21,20 @@ class RCTIdentifierPool { int dequeue() { - while (true) { + for (size_t attempt = 0; attempt < size; attempt++) { if (!usage[lastIndex]) { usage[lastIndex] = true; return lastIndex; } lastIndex = (lastIndex + 1) % size; } + + // Every identifier is taken, which only happens when identifiers were leaked. + // Reclaim them all instead of scanning forever: a reused identifier is a + // transient glitch, while an endless loop here hangs the main thread. + usage.reset(); + usage[lastIndex] = true; + return lastIndex; } void reset() @@ -39,7 +46,7 @@ class RCTIdentifierPool { private: std::bitset usage; - int lastIndex; + int lastIndex{0}; }; } // namespace facebook::react