Skip to content

Commit 84fbad6

Browse files
sherginfacebook-github-bot
authored andcommitted
Fabric: Safer UIManager deallocation and uninstallation
Summary: We have to uninstall UIManager synchronously to avoid a race condition when JS is capable to call already deallocated UIManager. Reviewed By: mdvacca Differential Revision: D10033406 fbshipit-source-id: 194d1ae2dd5ab09b036b1c165de289ada8e66014
1 parent 6af687d commit 84fbad6

File tree

2 files changed

+14
-8
lines changed

2 files changed

+14
-8
lines changed

ReactCommon/fabric/events/EventBeat.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ void EventBeat::beat() const {
1919
return;
2020
}
2121

22-
if (!beatCallback_) {
23-
return;
24-
}
25-
26-
beatCallback_();
2722
isRequested_ = false;
23+
24+
if (beatCallback_) {
25+
beatCallback_();
26+
}
2827
}
2928

3029
void EventBeat::induce() const {

ReactCommon/fabric/uimanager/FabricUIManager.cpp

+10-3
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,16 @@ static const std::string componentNameByReactViewName(std::string viewName) {
104104
}
105105

106106
FabricUIManager::~FabricUIManager() {
107-
(*executor_)([this] {
108-
uninstaller_();
109-
});
107+
// We move `executor_` and `uninstaller_` inside a lambda to extend their
108+
// life-time until the lambda finishes.
109+
auto executor = std::shared_ptr<EventBeatBasedExecutor> {std::move(executor_)};
110+
auto uninstaller = std::move(uninstaller_);
111+
112+
// We have to call this synchronously to postpose UIManager deallocation
113+
// until it is fully uninstalled and JavaScript cannot access this anymore.
114+
(*executor)([uninstaller, executor]() {
115+
uninstaller();
116+
}, EventBeatBasedExecutor::Mode::Synchronous);
110117
}
111118

112119
void FabricUIManager::setComponentDescriptorRegistry(const SharedComponentDescriptorRegistry &componentDescriptorRegistry) {

0 commit comments

Comments
 (0)