Open oblador opened 2 months ago
This appears to crash due to this assert fn call failing
template <typename T>
inline std::shared_ptr<T> Object::getHostObject(Runtime& runtime) const {
assert(isHostObject<T>(runtime));
return std::static_pointer_cast<T>(runtime.getHostObject(*this));
}
This is at the top of the end of the call stack initiated by RuntimeSchedulerBinding::getBinding(runtime)
inside requestIdleCallback here
If we comment out the assert call, everything appears to work okay. We correctly get the binding and can access the runtimeScheduler and the crash goes away.
@brentvatne could expo be somehow interfering with this runtime scheduler? This is blocking our release of rn75 which is supposedly compatible with sdk 51
Thank you for filing this issue! This comment acknowledges we believe this may be a bug and there’s enough information to investigate it. However, we can’t promise any sort of timeline for resolution. We prioritize issues based on severity, breadth of impact, and alignment with our roadmap. If you’d like to help move it more quickly, you can continue to investigate it more deeply and/or you can open a pull request that fixes the cause.
update for my investigation today: the main difference is whether soloader is enabled and i think that's an issue from react-native core. it could be resolved by 0.76 given all so libs are merged into single libreactnative.so
one workaround is to load libfabricjni.so first
--- a/android/app/src/main/java/com/requestidlecallbackissue/MainApplication.kt
+++ b/android/app/src/main/java/com/requestidlecallbackissue/MainApplication.kt
@@ -39,6 +39,11 @@ class MainApplication : Application(), ReactApplication {
super.onCreate()
SoLoader.init(this, false)
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
+ // Workaround to `facebook::react::RuntimeSchedulerBinding::getBinding` dynamic_cast error
+ // because of the symbol exists in multiple places.
+ // libfabricjni.so is the correct lib and we try to load it first.
+ System.loadLibrary("fabricjni")
+
// If you opted-in for the New Architecture, we load the native entry point for this app.
load()
}
will update more details and also try whether 0.76 resolved the issue tomorrow
i can confirm the issue also happens on rnc-cli 0.75 with enabled soloader and all this problem would be resolved from 0.76.
assert(isHostObject<T>(runtime))
. the object is actually a host object, but it fails because dynamic_cast returns null. it could because the type be used across lib boundary.libfabricjni.so
* frame #0: 0x00000071c52c9aec libfabricjni.so`facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime=0xb4000072b00a4410, runtimeScheduler=std::__ndk1::shared_ptr<facebook::react::RuntimeScheduler>::element_type @ 0xb4000072b00a4be8 strong=2 weak=3) at RuntimeSchedulerBinding.cpp:36:5
frame #1: 0x00000071c19868b8 librninstance.so`facebook::react::ReactInstance::initializeRuntime(facebook::react::ReactInstance::JSRuntimeFlags, std::__ndk1::function<void (facebook::jsi::Runtime&)>)::$_0::operator()(this=0xb4000073cfe50ed0, runtime=0xb4000072b00a4410) const at ReactInstance.cpp:346:5
frame #2: 0x00000071c198683c librninstance.so`decltype(std::declval<facebook::react::ReactInstance::initializeRuntime(facebook::react::ReactInstance::JSRuntimeFlags, std::__ndk1::function<void (facebook::jsi::Runtime&)>)::$_0&>()(std::declval<facebook::jsi::Runtime&>())) std::__ndk1::__invoke[abi:v170000]<facebook::react::ReactInstance::initializeRuntime(facebook::react::ReactInstance::JSRuntimeFlags, std::__ndk1::function<void (facebook::jsi::Runtime&)>)::$_0&, facebook::jsi::Runtime&>(__f=0xb4000073cfe50ed0, __args=0xb4000072b00a4410) at invoke.h:394:23
libreactnativejni.so
* frame #0: 0x00000071d4f72350 libreactnativejni.so`facebook::react::RuntimeSchedulerBinding::getBinding(runtime=0xb4000072b00a4410) at RuntimeSchedulerBinding.cpp:61:3
frame #1: 0x0000007246d221e8 libreact_nativemodule_defaults.so`facebook::react::NativeIdleCallbacks::requestIdleCallback(this=0xb40000743ff5d008, runtime=0xb4000072b00a4410, userCallback=0x0000007243a22fd0, options= Has Value=false ) at NativeIdleCallbacks.cpp:85:18
frame #2: 0x0000007246d254cc libreact_nativemodule_defaults.so`facebook::jsi::Value facebook::react::bridging::callFromJs<facebook::jsi::Value, facebook::react::NativeIdleCallbacks, facebook::jsi::Object, facebook::react::SyncCallback<void (facebook::jsi::Object)>&&, std::__ndk1::optional<facebook::react::NativeIdleCallbacksRequestIdleCallbackOptions<std::__ndk1::optional<double>>>, facebook::jsi::Function, std::__ndk1::optional<facebook::jsi::Object>>(rt=0xb4000072b00a4410, method=(libreact_nativemodule_defaults.so`facebook::react::NativeIdleCallbacks::requestIdleCallback(facebook::jsi::Runtime&, facebook::react::SyncCallback<void (facebook::jsi::Object)>&&, std::__ndk1::optional<facebook::react::NativeIdleCallbacksRequestIdleCallbackOptions<std::__ndk1::optional<double>>>) at NativeIdleCallbacks.cpp:84), jsInvoker=std::__ndk1::shared_ptr<facebook::react::CallInvoker>::element_type @ 0xb400007330239290 strong=27 weak=3, instance=0xb40000743ff5d008, args=0x0000007243a230f0, args= Has Value=false ) at Class.h:49:9
libfabricjni.so
and libreactnativejni.so
(could examine this by nm
or objdump
). since we install binding from libfabricjni.so::RuntimeSchduler
but get the binding from libreactnativejni.so::RuntimeSchduler
. the type inconsistency makes the dynamic_cast failure.libreactnativejni.so
will be loaded first and being used for libreact_nativemodule_defaults.so::requestIdleCallback() -> RuntimeSchedulerBinding::getBinding()
resolution.SoLoader.loadLibrary()
is equivalent to System.loadLibrary()
. it just loads the lib without loading deps first. in this case, libfabricjni.so
will be loaded earlier than libreactnativejni.so
.System.loadLibrary("fabricjni")
beforehand. it tries to load libfabricjni.so
as early as possible no matter soloader is enabled or not. it makes the RuntimeSchedulerBinding resolution consistent between install bindings and get bindings.since 0.76 will resolve the problem by the effort of merging solibs, i have no idea whether the workaround could be a formal solution. let me discuss this problem with meta how we resolve the problem on 0.75.
Minimal reproducible example
https://github.com/oblador/expo-requestidlecallback-issue
What platform(s) does this occur on?
Android
Where did you reproduce the issue?
in a development build
Summary
On latest stable
react-native
(0.75.3) andexpo
(51.0.32) with new architecture enabled on Android, callingrequestIdleCallback()
causes the app to crash. This doesn't happen when removing expo or disabling new architecture.I understand that 51 is built with 0.74 in mind, but it has been publicly stated that it is compatible with 0.75. Also 0.74 does not have
requestIdleCallback
implemented on bridgeless mode.Error message:
Potentially related: #31559
Environment
Expo Doctor Diagnostics