Describe the issue
onnxruntime-react-native (1.24.3, iOS) crashes with EXC_BAD_ACCESS on bridge teardown / fast refresh / app close. The faulting frame is -[OnnxruntimeModule dealloc] → std::shared_ptr<onnxruntimejsi::Env>::reset → facebook::jsi::WeakObject::~WeakObject() → null deref.
Root cause
OnnxruntimeModule.mm clears the static env shared_ptr inside -dealloc:
static std::shared_ptr<onnxruntimejsi::Env> env;
...
- (void)dealloc {
env.reset();
}
env holds JSI WeakObjects bound to the bridge's JSI runtime. React Native's teardown order is roughly:
- Bridge marks modules invalid (
invalidate)
- JSI runtime is destroyed
- Module Obj-C instances are released (
dealloc)
By step 3 the runtime is already gone, so ~WeakObject() accesses freed memory and segfaults. This is reliably reproducible on cold-launch followed by app close, on fast refresh, and on bridge reload.
Crash signature (iOS sim, RN 0.81, Hermes)
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000
Thread (com.facebook.react.runtime.JavaScript):
facebook::jsi::Pointer::~Pointer()
facebook::jsi::WeakObject::~WeakObject()
std::shared_ptr<facebook::jsi::WeakObject>::~shared_ptr()
onnxruntimejsi::Env::~Env()
std::shared_ptr<onnxruntimejsi::Env>::reset()
-[OnnxruntimeModule dealloc]
AutoreleasePoolPage::releaseUntil(...)
objc_autoreleasePoolPop
facebook::react::RCTMessageThread::runAsync(...)
Fix
Move the env.reset() out of dealloc into -invalidate (RN's documented hook that fires BEFORE the JSI runtime is torn down). Adopt RCTInvalidating:
@interface OnnxruntimeModule () <RCTInvalidating>
@end
@implementation OnnxruntimeModule
...
- (void)invalidate {
env.reset(); // runtime is still alive here; WeakObjects can die safely
}
- (void)dealloc {
// no-op: env already cleared in -invalidate
}
@end
I'm running this locally as a patch-package patch and the crash is gone. Happy to send a PR if useful — just wanted to file the issue first in case there's context on why the static env is owned by the module instance rather than a runtime-scoped install/uninstall pair.
Reproduction steps
- Install
onnxruntime-react-native@1.24.3 in a vanilla Expo 54 / RN 0.81 app
- Call
InferenceSession.create(...) once at startup so the JSI install runs
- Close the app or trigger a fast refresh
EXC_BAD_ACCESS appears in ~/Library/Logs/DiagnosticReports/ immediately
Urgency
Medium — the crash is on teardown so users on RC builds usually don't see it, but it shows up in TestFlight crash logs and breaks dev fast-refresh on any project that pulls in the package.
Platform
iOS (sim + device, arm64). Android is unaffected — the JNI module clears its refs differently.
Version
onnxruntime-react-native 1.24.3, React Native 0.81, iOS 18.x simulator + device, Hermes.
Describe the issue
onnxruntime-react-native(1.24.3, iOS) crashes withEXC_BAD_ACCESSon bridge teardown / fast refresh / app close. The faulting frame is-[OnnxruntimeModule dealloc]→std::shared_ptr<onnxruntimejsi::Env>::reset→facebook::jsi::WeakObject::~WeakObject()→ null deref.Root cause
OnnxruntimeModule.mmclears the staticenvshared_ptr inside-dealloc:envholds JSIWeakObjects bound to the bridge's JSI runtime. React Native's teardown order is roughly:invalidate)dealloc)By step 3 the runtime is already gone, so
~WeakObject()accesses freed memory and segfaults. This is reliably reproducible on cold-launch followed by app close, on fast refresh, and on bridge reload.Crash signature (iOS sim, RN 0.81, Hermes)
Fix
Move the
env.reset()out ofdeallocinto-invalidate(RN's documented hook that fires BEFORE the JSI runtime is torn down). AdoptRCTInvalidating:I'm running this locally as a
patch-packagepatch and the crash is gone. Happy to send a PR if useful — just wanted to file the issue first in case there's context on why the staticenvis owned by the module instance rather than a runtime-scoped install/uninstall pair.Reproduction steps
onnxruntime-react-native@1.24.3in a vanilla Expo 54 / RN 0.81 appInferenceSession.create(...)once at startup so the JSI install runsEXC_BAD_ACCESSappears in~/Library/Logs/DiagnosticReports/immediatelyUrgency
Medium — the crash is on teardown so users on RC builds usually don't see it, but it shows up in TestFlight crash logs and breaks dev fast-refresh on any project that pulls in the package.
Platform
iOS (sim + device, arm64). Android is unaffected — the JNI module clears its refs differently.
Version
onnxruntime-react-native1.24.3, React Native 0.81, iOS 18.x simulator + device, Hermes.