Avoid using RCTUnsafeExecuteOnMainQueueSync
and similar synchronous main queue dispatch methods as they can cause deadlocks, especially in initialization code, dispatch_once blocks, or when called from background threads that may already hold main queue dependencies.
Deadlocks occur when the main queue is waiting for a background queue, and that background queue then tries to synchronously dispatch back to the main queue. This creates a circular dependency where both queues are blocked waiting for each other.
Instead, use asynchronous alternatives like RCTExecuteOnMainQueue
which avoids the jump if already on the main queue, or standard dispatch_async(dispatch_get_main_queue(), ...)
when you need to ensure execution at the end of the main queue.
Example of problematic code:
// BAD - Can cause deadlock
- (void)invalidate {
RCTUnsafeExecuteOnMainQueueSync(^{
if (_didInvalidate) {
return;
}
// ... invalidation logic
});
}
Example of safer alternative:
// GOOD - Uses async dispatch to avoid deadlock
- (void)invalidate {
RCTExecuteOnMainQueue(^{
if (_didInvalidate) {
return;
}
// ... invalidation logic
});
}
This pattern is particularly important in React Native’s multi-threaded environment where JavaScript, UI, and background threads frequently interact.
Enter the URL of a public GitHub repository