A framework for building native applications using React
Fix use-after-free during hot reload on macOS (#55277)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/55277 Fixes a crash occurring during Metro hot reload on macOS after prolonged sessions (15+ minutes) - P2129051751: ``` :horizon::(anonymous namespace)::handleSignal(int, __siginfo*, void*) :_sigtramp :std::__1::__hash_const_iterator<std::__1::__hash_node<std::__1::__hash_value_type<int, std::__1::unique_ptr<facebook::react::AnimatedNode, std::__1::default_delete<facebook::react::AnimatedNode>>>, void*>*> std::__1::__hash_table<std::__1::__hash_value_type<int, std::__1::unique_ptr<facebook::react::AnimatedNode, std::__1::default_delete<facebook::react::AnimatedNode>>>, std::__1::__unordered_map_hasher<int, std::__1::__hash_value_type<int, std::__1::unique_ptr<facebook::react::AnimatedNode, std::__1::default_delete<facebook::react::AnimatedNode>>>, std::__1::hash<int>, std::__1::equal_to<int>, true>, std::__1::__unordered_map_equal<int, std::__1::__hash_value_type<int, std::__1::unique_ptr<facebook::react::AnimatedNode, std::__1::default_delete<facebook::react::AnimatedNode>>>, std::__1::equal_to<int>, std::__1::hash<int>, true>, std::__1::allocator<std::__1::__hash_value_type<int, std::__1::unique_ptr<facebook::react::AnimatedNode, std::__1::default_delete<facebook::react::AnimatedNode>>>>>::find<int>(int const&) const :std::__1::unordered_map<int, std::__1::unique_ptr<facebook::react::AnimatedNode, std::__1::default_delete<facebook::react::AnimatedNode>>, std::__1::hash<int>, std::__1::equal_to<int>, std::__1::allocator<std::__1::pair<int const, std::__1::unique_ptr<facebook::react::AnimatedNode, std::__1::default_delete<facebook::react::AnimatedNode>>>>>::find[abi:ne200100](int const&) const :facebook::react::AnimatedNode* facebook::react::NativeAnimatedNodesManager::getAnimatedNode<facebook::react::AnimatedNode, void>(int) const requires std::is_base_of_v<facebook::react::AnimatedNode, facebook::react::AnimatedNode> :facebook::react::NativeAnimatedNodesManager::updateNodes(std::__1::set<int, std::__1::less<int>, std::__1::allocator<int>> const&) :facebook::react::NativeAnimatedNodesManager::onAnimationFrame(double) :facebook::react::NativeAnimatedNodesManager::onRender() :facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0::operator()() const :decltype(std::declval<facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0&>()()) std::__1::__invoke[abi:ne200100]<facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0&>(facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0&) :void std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:ne200100]<facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0&>(facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0&) :void std::__1::__invoke_r[abi:ne200100]<void, facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0&>(facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0&) :std::__1::__function::__alloc_func<facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0, std::__1::allocator<facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0>, void ()>::operator()[abi:ne200100]() :std::__1::__function::__func<facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0, std::__1::allocator<facebook::react::NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool)::$_0>, void ()>::operator()() :std::__1::__function::__value_func<void ()>::operator()[abi:ne200100]() const :std::__1::function<void ()>::operator()() const :-[RCTAnimatedModuleProvider _onDisplayLinkTick] :-[RCTPlatformDisplayLink tick] :__RCTPlatformDisplayLinkCallBack_block_invoke :__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ :__CFRunLoopDoBlocks :__CFRunLoopRun :_CFRunLoopRunSpecificWithOptions :RunCurrentEventLoopInMode :ReceiveNextEventCommon :_BlockUntilNextEventMatchingListInMode :_DPSBlockUntilNextEventMatchingListInMode :_DPSNextEvent :-[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] :-[NSApplication(NSEventRouting) nextEventMatchingMask:untilDate:inMode:dequeue:] :-[NSApplication(RCTTouchHandlerOverride) override_nextEventMatchingMask:untilDate:inMode:dequeue:] :-[NSApplication(RCTSurfaceTouchHandlerOverride) override_surface_nextEventMatchingMask:untilDate:inMode:dequeue:] :-[NSApplication run] :main :Stack End ``` The display link callback was checking if the animation provider was alive but not holding a strong reference during callback execution. This allowed the NativeAnimatedNodesManager to be destroyed mid-callback, causing a use-after-free. By storing the result of weak_ptr::lock() in a local variable, we ensure the provider (and its managed NativeAnimatedNodesManager) remains alive for the entire duration of the _onRender() callback. Changelog: [Internal] Differential Revision: D91236980 fbshipit-source-id: dff6035176c1d2eb4d61c668b5a6311e5e4521d4
Y
Yannick Loriot committed
05921817a9be4e2cf114102ed2cef6c38b5b1cf1
Parent: afb6847
Committed by meta-codesync[bot] <215208954+meta-codesync[bot]@users.noreply.github.com>
on 1/22/2026, 11:02:04 PM