Commit 0592181
Fix use-after-free during hot reload on macOS (#55277)
Summary:
Pull Request resolved: #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: dff6035176c1d2eb4d61c668b5a6311e5e4521d41 parent afb6847 commit 0592181
1 file changed
Lines changed: 6 additions & 1 deletion
Lines changed: 6 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
60 | | - | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
61 | 66 | | |
62 | 67 | | |
63 | 68 | | |
| |||
0 commit comments