Skip to content

Fix AnimationBackend choreographer deadlock with synchronous VirtualView events#57060

Closed
coado wants to merge 1 commit into
react:mainfrom
coado:export-D107378627
Closed

Fix AnimationBackend choreographer deadlock with synchronous VirtualView events#57060
coado wants to merge 1 commit into
react:mainfrom
coado:export-D107378627

Conversation

@coado

@coado coado commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Summary:
When the shared animation backend is enabled, starting/stopping a native animation calls AnimationBackendChoreographer.resume()/pause() on the thread
that started the animation, which can be the JS thread. The resume() method posted a frame callback to ReactChoreographer, acquiring the choreographer's callback queue. The UI thread might simultaneously hold that lock while dispatching a synchronous event through executeSynchronouslyOnSameThread_CAN_DEADLOCK. That path is chose after invoking the VirtualView Visible mode-change event. The executeSynchronouslyOnSameThread_CAN_DEADLOCK blocks main thread to access jsi::Runtime from the JS thread while holding a lock on the callbacks queue. There is a chance that resuming animation and the synchronous event will collide, as the first one tries to post a callback to the queue from the JS thread, waiting for release while the other holds a lock on that queue and waits for the JS thread to pass the runtime, causing a deadlock.

The fix is to keep the choreographer frame callback permanently registered. It is posted once on the UI thread and re-posts itself every frame, running as a no-op while paused. The resume and pause methods now only toggle so accessing the lock on the callback queue is not necessary.

Changelog:
[Android][Fixed] - Fix deadlock between the UI and JS threads when native animations start while a synchronous VirtualView mode-change event is dispatched

Differential Revision: D107378627

…iew events

Summary:
When the shared animation backend is enabled, starting/stopping a native animation calls `AnimationBackendChoreographer.resume()/pause()` on the thread
that started the animation, which can be the **JS thread**. The `resume()` method posted a frame callback to ReactChoreographer, acquiring the choreographer's callback queue. The UI thread might simultaneously hold that lock while dispatching a synchronous event through `executeSynchronouslyOnSameThread_CAN_DEADLOCK`. That path is chose after invoking the VirtualView `Visible` mode-change event. The `executeSynchronouslyOnSameThread_CAN_DEADLOCK` blocks main thread to access `jsi::Runtime` from the JS thread while holding a lock on the callbacks queue. There is a chance that resuming animation and the synchronous event will collide, as the first one tries to post a callback to the queue from the JS thread, waiting for release while the other holds a lock on that queue and waits for the JS thread to pass the runtime, causing a deadlock.

The fix is to keep the choreographer frame callback permanently registered. It is posted once on the UI thread and re-posts itself every frame, running as a no-op while paused. The `resume` and `pause` methods now only toggle so accessing the lock on the callback queue is not necessary. 

Changelog:
[Android][Fixed] - Fix deadlock between the UI and JS threads when native animations start while a synchronous VirtualView mode-change event is dispatched

Differential Revision: D107378627
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jun 3, 2026
@facebook-github-tools facebook-github-tools Bot added p: Software Mansion Partner: Software Mansion Partner labels Jun 3, 2026
@meta-codesync

meta-codesync Bot commented Jun 3, 2026

Copy link
Copy Markdown

@coado has exported this pull request. If you are a Meta employee, you can view the originating Diff in D107378627.

@facebook-github-tools facebook-github-tools Bot added the p: Facebook Partner: Facebook label Jun 3, 2026
@meta-codesync meta-codesync Bot closed this in b96b626 Jun 3, 2026
@facebook-github-tools facebook-github-tools Bot added the Merged This PR has been merged. label Jun 3, 2026
@meta-codesync

meta-codesync Bot commented Jun 3, 2026

Copy link
Copy Markdown

This pull request has been merged in b96b626.

@react-native-bot

Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @coado in b96b626

When will my fix make it into a release? | How to file a pick request?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported Merged This PR has been merged. meta-exported p: Facebook Partner: Facebook p: Software Mansion Partner: Software Mansion Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants