Skip to content

Commit 6e701ce

Browse files
javachefacebook-github-bot
authored andcommitted
Fix crash on arm32 when configuring eventEmitterCallback (facebook#50592)
Summary: Pull Request resolved: facebook#50592 For unclear reasons this is crashing on some devices when dereferencing the module ref. Instead we can just access the existing global_ref to the module instance and avoid any deallocation timing issues. Also added some additional safeguards and validation against incorrect JNI invocations. Changelog: [Android][Fixed] Fix crash when TurboModule event emitters are used on arm32 Reviewed By: cortinico Differential Revision: D72716972 fbshipit-source-id: 3803329048d8388b3d30c9cb55a857e399569eea
1 parent 029d41d commit 6e701ce

5 files changed

Lines changed: 22 additions & 23 deletions

File tree

packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ ${methods
8484
}${
8585
eventEmitters.length > 0
8686
? `
87-
setEventEmitterCallback(params.instance);`
87+
configureEventEmitterCallback();`
8888
: ''
8989
}
9090
}`.trim();

packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo
202202
eventEmitterMap_[\\"onEvent4\\"] = std::make_shared<AsyncEventEmitter<folly::dynamic>>();
203203
eventEmitterMap_[\\"onEvent5\\"] = std::make_shared<AsyncEventEmitter<folly::dynamic>>();
204204
eventEmitterMap_[\\"onEvent6\\"] = std::make_shared<AsyncEventEmitter<folly::dynamic>>();
205-
setEventEmitterCallback(params.instance);
205+
configureEventEmitterCallback();
206206
}
207207
208208
std::shared_ptr<TurboModule> event_emitter_module_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams &params) {
@@ -486,7 +486,7 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo
486486
: JavaTurboModule(params) {
487487
methodMap_[\\"getStringLiteral\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getStringLiteral};
488488
eventEmitterMap_[\\"literalEvent\\"] = std::make_shared<AsyncEventEmitter<folly::dynamic>>();
489-
setEventEmitterCallback(params.instance);
489+
configureEventEmitterCallback();
490490
}
491491
492492
std::shared_ptr<TurboModule> string_literals_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams &params) {

packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -970,34 +970,28 @@ jsi::Value JavaTurboModule::invokeJavaMethod(
970970
}
971971
}
972972

973-
void JavaTurboModule::setEventEmitterCallback(
974-
jni::alias_ref<jobject> jinstance) {
973+
void JavaTurboModule::configureEventEmitterCallback() {
975974
JNIEnv* env = jni::Environment::current();
976-
auto instance = jinstance.get();
977975
static jmethodID cachedMethodId = nullptr;
978976
if (cachedMethodId == nullptr) {
979-
jclass cls = env->GetObjectClass(instance);
977+
jclass cls = env->GetObjectClass(instance_.get());
980978
cachedMethodId = env->GetMethodID(
981979
cls,
982980
"setEventEmitterCallback",
983981
"(Lcom/facebook/react/bridge/CxxCallbackImpl;)V");
982+
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
984983
}
985984

986-
auto eventEmitterLookup =
987-
[&](const std::string& eventName) -> AsyncEventEmitter<folly::dynamic>& {
988-
return static_cast<AsyncEventEmitter<folly::dynamic>&>(
989-
*eventEmitterMap_[eventName].get());
990-
};
991-
992985
jvalue arg;
993-
arg.l = JCxxCallbackImpl::newObjectCxxArgs([eventEmitterLookup = std::move(
994-
eventEmitterLookup)](
995-
folly::dynamic args) {
996-
auto eventName = args.at(0).asString();
997-
auto eventArgs = args.size() > 1 ? args.at(1) : nullptr;
998-
eventEmitterLookup(eventName).emit(std::move(eventArgs));
999-
}).release();
1000-
env->CallVoidMethod(instance, cachedMethodId, arg);
986+
arg.l =
987+
JCxxCallbackImpl::newObjectCxxArgs([&](folly::dynamic args) {
988+
auto eventName = args.at(0).asString();
989+
auto& eventEmitter = static_cast<AsyncEventEmitter<folly::dynamic>&>(
990+
*eventEmitterMap_[eventName].get());
991+
eventEmitter.emit(args.size() > 1 ? std::move(args).at(1) : nullptr);
992+
}).release();
993+
env->CallVoidMethod(instance_.get(), cachedMethodId, arg);
994+
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
1001995
}
1002996

1003997
} // namespace facebook::react

packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ class JSI_EXPORT JavaTurboModule : public TurboModule {
5050
size_t argCount,
5151
jmethodID& cachedMethodID);
5252

53-
void setEventEmitterCallback(jni::alias_ref<jobject> instance);
53+
protected:
54+
void configureEventEmitterCallback();
55+
56+
[[deprecated]] void setEventEmitterCallback(jni::alias_ref<jobject>) {
57+
configureEventEmitterCallback();
58+
}
5459

5560
private:
5661
// instance_ can be of type JTurboModule, or JNativeModule

packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(
359359
std::make_shared<AsyncEventEmitter<folly::dynamic>>();
360360
eventEmitterMap_["onSubmit"] =
361361
std::make_shared<AsyncEventEmitter<folly::dynamic>>();
362-
setEventEmitterCallback(params.instance);
362+
configureEventEmitterCallback();
363363
}
364364

365365
std::shared_ptr<TurboModule> SampleTurboModuleSpec_ModuleProvider(

0 commit comments

Comments
 (0)