Skip to content

Commit

Permalink
Fix crash in RCTCoreModulesClassProvider during quit
Browse files Browse the repository at this point in the history
Summary:
This intentionally leaks the static map, since it still might be accessed after static destructors are run. This is a common approach to this problem, see #22607 and facebook/componentkit#906 as examples. It also sets up an autorelease pool from  `RCTNativeModule::invoke` as a precaution since there's no strict guarantee one exists when it is called.

Changelog:
[iOS][Fixed] - Fix crash in RCTCoreModulesClassProvider during quit

Reviewed By: RSNara

Differential Revision: D27932062

fbshipit-source-id: fa75da4b78290027a762440ac6943c81b8594a57
  • Loading branch information
appden authored and facebook-github-bot committed Apr 28, 2021
1 parent 08ea434 commit 2f62c28
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 28 deletions.
7 changes: 4 additions & 3 deletions Libraries/Blob/RCTBlobPlugins.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
#import <unordered_map>

Class RCTBlobClassProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"FileReaderModule", RCTFileReaderModuleCls},
{"BlobModule", RCTBlobManagerCls},
};

auto p = sCoreModuleClassMap.find(name);
if (p != sCoreModuleClassMap.end()) {
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
Expand Down
7 changes: 4 additions & 3 deletions Libraries/Image/RCTImagePlugins.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@
#import <unordered_map>

Class RCTImageClassProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"GIFImageDecoder", RCTGIFImageDecoderCls},
{"ImageEditingManager", RCTImageEditingManagerCls},
{"ImageLoader", RCTImageLoaderCls},
{"ImageStoreManager", RCTImageStoreManagerCls},
{"LocalAssetImageLoader", RCTLocalAssetImageLoaderCls},
};

auto p = sCoreModuleClassMap.find(name);
if (p != sCoreModuleClassMap.end()) {
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
Expand Down
7 changes: 4 additions & 3 deletions Libraries/LinkingIOS/RCTLinkingPlugins.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
#import <unordered_map>

Class RCTLinkingClassProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"LinkingManager", RCTLinkingManagerCls},
};

auto p = sCoreModuleClassMap.find(name);
if (p != sCoreModuleClassMap.end()) {
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
Expand Down
7 changes: 4 additions & 3 deletions Libraries/NativeAnimation/RCTAnimationPlugins.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
#import <unordered_map>

Class RCTAnimationClassProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"NativeAnimatedModule", RCTNativeAnimatedModuleCls},
{"NativeAnimatedTurboModule", RCTNativeAnimatedTurboModuleCls},
};

auto p = sCoreModuleClassMap.find(name);
if (p != sCoreModuleClassMap.end()) {
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
Expand Down
7 changes: 4 additions & 3 deletions Libraries/Network/RCTNetworkPlugins.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
#import <unordered_map>

Class RCTNetworkClassProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"Networking", RCTNetworkingCls},
{"DataRequestHandler", RCTDataRequestHandlerCls},
{"FileRequestHandler", RCTFileRequestHandlerCls},
{"HTTPRequestHandler", RCTHTTPRequestHandlerCls},
};

auto p = sCoreModuleClassMap.find(name);
if (p != sCoreModuleClassMap.end()) {
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
Expand Down
7 changes: 4 additions & 3 deletions Libraries/PushNotificationIOS/RCTPushNotificationPlugins.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
#import <unordered_map>

Class RCTPushNotificationClassProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"PushNotificationManager", RCTPushNotificationManagerCls},
};

auto p = sCoreModuleClassMap.find(name);
if (p != sCoreModuleClassMap.end()) {
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
Expand Down
7 changes: 4 additions & 3 deletions Libraries/Settings/RCTSettingsPlugins.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
#import <unordered_map>

Class RCTSettingsClassProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"SettingsManager", RCTSettingsManagerCls},
};

auto p = sCoreModuleClassMap.find(name);
if (p != sCoreModuleClassMap.end()) {
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
Expand Down
7 changes: 4 additions & 3 deletions Libraries/Vibration/RCTVibrationPlugins.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
#import <unordered_map>

Class RCTVibrationClassProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"Vibration", RCTVibrationCls},
};

auto p = sCoreModuleClassMap.find(name);
if (p != sCoreModuleClassMap.end()) {
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
Expand Down
7 changes: 4 additions & 3 deletions React/CoreModules/CoreModulesPlugins.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
#import <unordered_map>

Class RCTCoreModulesClassProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"AccessibilityManager", RCTAccessibilityManagerCls},
{"Appearance", RCTAppearanceCls},
{"DeviceInfo", RCTDeviceInfoCls},
Expand Down Expand Up @@ -45,8 +46,8 @@ Class RCTCoreModulesClassProvider(const char *name) {
{"EventDispatcher", RCTEventDispatcherCls},
};

auto p = sCoreModuleClassMap.find(name);
if (p != sCoreModuleClassMap.end()) {
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
Expand Down
4 changes: 3 additions & 1 deletion React/CxxModule/RCTNativeModule.mm
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ static MethodCallResult invokeInner(
#else
(void)(callId);
#endif
invokeInner(weakBridge, weakModuleData, methodId, std::move(params), callId, isSyncModule ? Sync : Async);
@autoreleasepool {
invokeInner(weakBridge, weakModuleData, methodId, std::move(params), callId, isSyncModule ? Sync : Async);
}
};

if (isSyncModule) {
Expand Down

0 comments on commit 2f62c28

Please sign in to comment.