fix: deadlock when sending events #33490
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
In short, if an RCTEventDispatcher observer sends an event on the same thread that the observer was initially on, there will be a deadlock due to
sendEvent
already having the lock active on the_observers
NSHashTable. An example where this occurred was when we had react-native-gesture-handler trigger an animated event, which then triggered an event on the underlying component being animated as a result of it being an observer on the animation event. Since this all occurred on the main thread, we ended up with a deadlock and the app froze.To prevent this scenario, I used a
NSRecursiveLock
for _observersLock to be able to dispatch events on the same thread from observers.@joebernard
Changelog
[iOS] [Fix] - Prevent deadlock when dispatching events from observers on the same thread.
Test Plan
Not sure if there are any tests present for sending events with RCTEventDispatcher already in place, but In regular app usage this solution has proved to be a viable and stable option so far and has prevented the deadlock from occurring.
This would still be thread-safe since we are now allowing the event to be sent through observers on the same thread the initial event was dispatched on. The only issue I could see here is the behavior of sending an event could be changed.