-
Notifications
You must be signed in to change notification settings - Fork 24.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pattern for interacting with the main thread #42
Comments
Oh haha. RTFM. It's actually pretty simple:
That works! |
If you are bored, would be awesome to compile this into some sort of docs :) |
I almost filed an issue about that, actually! I was going to ask if there's a place you want us to contribute to docs. I can certainly write done a bunch of small stuff I've learned. Where would you like it, and what format? |
We're going to have official docs before we open this repo to everyone. They'll be in the docs folder in markdown, the same way React is. If you can start writing them in markdown and in the docs folder with whatever you think is useful for people, that would be awesome! |
Looks like this is a very common pattern - native modules that run on main thread. Maybe we could do something like: - (void)loadMesh:(NSString *)path {
RCT_EXPORT_ON_MAIN_THREAD();
node.mesh = [REMeshCache meshNamed:path];
} @a2 / @nicklockwood - any thoughts? |
The JS bridge is meant to be asynchronous and therefore runs off the main thread. I personally think that if something should happen on a specific thread/queue, it is the caller's responsibility. Apple's documentation often says that callbacks can happen on private threads/queues and that you should dispatch if necessary. |
@a2 great answer, totally makes sense! |
Whilst @a2 is quite correct, I wonder if it might make sense to change the thread that we call back to modules on to main. We don't call module methods on the JS thread, we actually call them on the shadow thread, which is a seperate thread used by the RCTUIManager to do layout calculations. But other than the UIManager, the vast majority of modules either don't care what thread they run on, or would prefer to run their methods on the main thread. Perhaps then, the bridge should call back to main, and the UIManager can dispatch to the shadow thread? It would save having to dispatch_async inside every single module's methods for the sake of catering to the requirements of one specific module. |
…crash on simulator, on device I got nothing but app freezed)! My app has an old version of JSONKit which is still using MRC. I think JSONKit is not needed if system version is available. Kicking out of JSONKit will make react native stronger. Crash stack: * thread facebook#11: tid = 0xbd672f, 0x000000010a10edeb imobii-waiqin`jk_encode_add_atom_to_buffer(encodeState=0x00007f9b820a1000, objectPtr=22 key/value pairs) + 16971 at JSONKit.m:2807, name = 'com.facebook.React.JavaScript', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) frame #0: 0x000000010a10edeb imobii-waiqin`jk_encode_add_atom_to_buffer(encodeState=0x00007f9b820a1000, objectPtr=22 key/value pairs) + 16971 at JSONKit.m:2807 frame facebook#1: 0x000000010a10ef67 imobii-waiqin`jk_encode_add_atom_to_buffer(encodeState=0x00007f9b820a1000, objectPtr=2 key/value pairs) + 17351 at JSONKit.m:2811 frame facebook#2: 0x000000010a10ef67 imobii-waiqin`jk_encode_add_atom_to_buffer(encodeState=0x00007f9b820a1000, objectPtr=25 key/value pairs) + 17351 at JSONKit.m:2811 frame facebook#3: 0x000000010a10e768 imobii-waiqin`jk_encode_add_atom_to_buffer(encodeState=0x00007f9b820a1000, objectPtr=@"3 elements") + 15304 at JSONKit.m:2778 * frame facebook#4: 0x000000010a10a26a imobii-waiqin`-[JKSerializer serializeObject:options:encodeOption:block:delegate:selector:error:](self=0x00007f9b831fbc80, _cmd="serializeObject:options:encodeOption:block:delegate:selector:error:", object=@"3 elements", optionFlags=0, encodeOption=10, block=0x0000000000000000, delegate=0x0000000000000000, selector=<no value available>, error=domain: class name = NSInvocation - code: 0) + 2250 at JSONKit.m:2876 frame facebook#5: 0x000000010a109992 imobii-waiqin`+[JKSerializer serializeObject:options:encodeOption:block:delegate:selector:error:](self=JKSerializer, _cmd="serializeObject:options:encodeOption:block:delegate:selector:error:", object=@"3 elements", optionFlags=0, encodeOption=10, block=0x0000000000000000, delegate=0x0000000000000000, selector=<no value available>, error=domain: class name = NSInvocation - code: 0) + 178 at JSONKit.m:2831 frame facebook#6: 0x000000010a10f700 imobii-waiqin`-[NSArray(self=@"3 elements", _cmd="JSONStringWithOptions:error:", serializeOptions=0, error=domain: class name = NSInvocation - code: 0) JSONStringWithOptions:error:] + 112 at JSONKit.m:2985 frame facebook#7: 0x000000010ac13c02 imobii-waiqin`_RCTJSONStringifyNoRetry(jsonObject=@"3 elements", error=domain: class name = NSInvocation - code: 0) + 338 at RCTUtils.m:49 frame facebook#8: 0x000000010ac13990 imobii-waiqin`RCTJSONStringify(jsonObject=@"3 elements", error=0x0000000000000000) + 128 at RCTUtils.m:77 frame facebook#9: 0x000000010ab5fdfa imobii-waiqin`__27-[RCTContextExecutor setUp]_block_invoke_2(.block_descriptor=<unavailable>, moduleName=@"UIManager") + 218 at RCTContextExecutor.m:363 frame facebook#10: 0x00000001134495cc CoreFoundation`__invoking___ + 140 frame facebook#11: 0x000000011344941e CoreFoundation`-[NSInvocation invoke] + 286 frame facebook#12: 0x000000010db13db3 JavaScriptCore`JSC::ObjCCallbackFunctionImpl::call(JSContext*, OpaqueJSValue*, unsigned long, OpaqueJSValue const* const*, OpaqueJSValue const**) + 451 frame facebook#13: 0x000000010db13926 JavaScriptCore`JSC::objCCallbackFunctionCallAsFunction(OpaqueJSContext const*, OpaqueJSValue*, OpaqueJSValue*, unsigned long, OpaqueJSValue const* const*, OpaqueJSValue const**) + 262 frame facebook#14: 0x000000010db14bad JavaScriptCore`long long JSC::APICallbackFunction::call<JSC::ObjCCallbackFunction>(JSC::ExecState*) + 573 frame facebook#15: 0x000000010dade340 JavaScriptCore`JSC::LLInt::setUpCall(JSC::ExecState*, JSC::Instruction*, JSC::CodeSpecializationKind, JSC::JSValue, JSC::LLIntCallLinkInfo*) + 528 frame facebook#16: 0x000000010dae535d JavaScriptCore`llint_entry + 22900 frame facebook#17: 0x000000010dadf7d9 JavaScriptCore`vmEntryToJavaScript + 326 frame facebook#18: 0x000000010d9b1959 JavaScriptCore`JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) + 169 frame facebook#19: 0x000000010d9985ad JavaScriptCore`JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 493 frame facebook#20: 0x000000010d76cb7e JavaScriptCore`JSC::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 62 frame facebook#21: 0x000000010d929a55 JavaScriptCore`JSC::callGetter(JSC::ExecState*, JSC::JSValue, JSC::JSValue) + 149 frame facebook#22: 0x000000010dad49fb JavaScriptCore`llint_slow_path_get_by_id + 2203 frame facebook#23: 0x000000010dae22f0 JavaScriptCore`llint_entry + 10503 frame facebook#24: 0x000000010dae5368 JavaScriptCore`llint_entry + 22911 frame facebook#25: 0x000000010dae52fd JavaScriptCore`llint_entry + 22804 frame facebook#26: 0x000000010dae5368 JavaScriptCore`llint_entry + 22911 frame facebook#27: 0x000000010dae5368 JavaScriptCore`llint_entry + 22911 frame facebook#28: 0x000000010dae52fd JavaScriptCore`llint_entry + 22804 frame facebook#29: 0x000000010dae5368 JavaScriptCore`llint_entry + 22911 frame facebook#30: 0x000000010dae5368 JavaScriptCore`llint_entry + 22911 frame facebook#31: 0x000000010dae5368 JavaScriptCore`llint_entry + 22911 frame facebook#32: 0x000000010dae552a JavaScriptCore`llint_entry + 23361 frame facebook#33: 0x000000010dae5368 JavaScriptCore`llint_entry + 22911 frame facebook#34: 0x000000010dae5368 JavaScriptCore`llint_entry + 22911 frame facebook#35: 0x000000010dadf7d9 JavaScriptCore`vmEntryToJavaScript + 326 frame facebook#36: 0x000000010d9b1959 JavaScriptCore`JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) + 169 frame facebook#37: 0x000000010d998264 JavaScriptCore`JSC::Interpreter::execute(JSC::ProgramExecutable*, JSC::ExecState*, JSC::JSObject*) + 10404 frame facebook#38: 0x000000010d7a8786 JavaScriptCore`JSC::evaluate(JSC::ExecState*, JSC::SourceCode const&, JSC::JSValue, WTF::NakedPtr<JSC::Exception>&) + 470 frame facebook#39: 0x000000010d9f6fb8 JavaScriptCore`JSEvaluateScript + 424 frame facebook#40: 0x000000010ab6379e imobii-waiqin`__68-[RCTContextExecutor executeApplicationScript:sourceURL:onComplete:]_block_invoke.264(.block_descriptor=<unavailable>) + 414 at RCTContextExecutor.m:589 frame facebook#41: 0x000000010ab63262 imobii-waiqin`__68-[RCTContextExecutor executeApplicationScript:sourceURL:onComplete:]_block_invoke(.block_descriptor=<unavailable>) + 498 at RCTContextExecutor.m:589 frame facebook#42: 0x000000010ab63df8 imobii-waiqin`-[RCTContextExecutor executeBlockOnJavaScriptQueue:](self=0x00007f9b832f6040, _cmd="executeBlockOnJavaScriptQueue:", block=0x00007f9b80c92970) + 248 at RCTContextExecutor.m:627 frame facebook#43: 0x000000010eb1d7a7 Foundation`__NSThreadPerformPerform + 283 frame facebook#44: 0x0000000113486301 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 frame facebook#45: 0x000000011347c22c CoreFoundation`__CFRunLoopDoSources0 + 556 frame facebook#46: 0x000000011347b6e3 CoreFoundation`__CFRunLoopRun + 867 frame facebook#47: 0x000000011347b0f8 CoreFoundation`CFRunLoopRunSpecific + 488 frame facebook#48: 0x000000010ab5e41b imobii-waiqin`+[RCTContextExecutor runRunLoopThread](self=RCTContextExecutor, _cmd="runRunLoopThread") + 363 at RCTContextExecutor.m:284 frame facebook#49: 0x000000010ebc012b Foundation`__NSThread__start__ + 1198 frame facebook#50: 0x00000001140869b1 libsystem_pthread.dylib`_pthread_body + 131 frame facebook#51: 0x000000011408692e libsystem_pthread.dylib`_pthread_start + 168 frame facebook#52: 0x0000000114084385 libsystem_pthread.dylib`thread_start + 13
I exported a function on my controller:
This is called when selecting an item from a list:
I've been trying to debug why OpenGL crashes, and I finally realized that my OpenGL context doesn't exist. Which made me realize that this method in Obj-C is not running on the main thread. It's running in a different thread which all calls into Obj-C seem to run on.
I'm not familiar with iOS, so this is over my head. Is there a simple pattern I can use to interact with the main thread? How do I send a message to it?
I realize this not usually needed, and most custom native modules can probably be run standalone, but I'm basically implementing a custom view that needs to render on the main thread (not technically true, just a custom controller to a normal view, but still).
The text was updated successfully, but these errors were encountered: