Skip to content

fix(resizer): guard dispose() against an in-flight resize() - #4130

Open
jslok wants to merge 1 commit into
mrousavy:mainfrom
jslok:fix/resizer-dispose-race
Open

fix(resizer): guard dispose() against an in-flight resize()#4130
jslok wants to merge 1 commit into
mrousavy:mainfrom
jslok:fix/resizer-dispose-race

Conversation

@jslok

@jslok jslok commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Split out of #4117 (as requested).

resize() null-checks _pipeline and then dereferences it with no synchronization, while dispose() can concurrently reset the same unique_ptr from the JS thread — running ~VulkanResizerPipeline() and tearing down the VkDevice under an in-flight run(). That is a native use-after-free instead of the catchable "already been disposed" error. iOS has the same shape: an unguarded pipeline = nil racing the guard let load is a data race on the possibly-last reference.

Fix: serialize resize(), dispose() and the memorySize getter behind a lifecycle lock (std::mutex / NSLock). A dispose landing mid-frame blocks until that resize returns; every later call throws the catchable error. The getter is included because Nitro reads it from toObject() on arbitrary threads; it is never called from inside resize()/dispose(), so it cannot self-deadlock.

Tested on device on both platforms: on Android by disposing from an effect cleanup while frames were still being processed, and on iOS where this change has been shipping in our production app as a patch-package patch.

🤖 Generated with Claude Code

resize() dereferenced the pipeline with no synchronization while dispose()
could concurrently destroy it from the JS thread - a native use-after-free
instead of the catchable "already been disposed" error. Serialize resize(),
dispose() and the memorySize getter behind a lifecycle lock on both platforms.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

@jslok is attempting to deploy a commit to the Margelo Team on Vercel.

A member of the Team first needs to authorize it.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant