fix: serialize CreateCodeCache against Isolate.Dispose via RWMutex#9
Merged
Conversation
V8 14.x shares process-global state between isolates (ReadOnlySpace, StringForwardingTable, pointer compression cage). snapshotDeserMu already serializes NewIsolate and Dispose against each other, but CreateCodeCache was unprotected — it reads SharedFunctionInfo which references shared-heap objects that Dispose can tear down concurrently. Under 12-worker concurrency this causes SIGSEGV at address 0x0 in UnboundScriptCreateCodeCache when the ISOLATE_SCOPE macro dereferences a null or freed isolate pointer. Changes: - Upgrade snapshotDeserMu from sync.Mutex to sync.RWMutex. Dispose/NewIsolate take Lock (exclusive writer); CreateCodeCache takes RLock (shared reader). Multiple concurrent CreateCodeCache calls on different isolates remain parallel. - Move i.ptr = nil inside the write lock in Dispose to close the TOCTOU window where a dangling pointer was visible after unlock. - Add nil guards in CreateCodeCache (Go layer) before and after acquiring RLock, plus a null check in the C layer before ISOLATE_SCOPE to prevent dereferencing NULL.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
UnboundScriptCreateCodeCacheunder concurrent multi-isolate workloads (12+ Playwright workers).snapshotDeserMuserializedNewIsolate/Disposebut leftCreateCodeCacheunprotected — it reads V8 shared-heap state (SharedFunctionInfo,StringForwardingTable,ReadOnlySpaceroots) thatDisposetears down concurrently.snapshotDeserMufromsync.Mutextosync.RWMutex:Dispose/NewIsolatetake exclusiveLock();CreateCodeCachetakes sharedRLock(). Multiple concurrentCreateCodeCachecalls remain parallel.i.ptr = nilwas set aftersnapshotDeserMu.Unlock(), leaving a dangling-pointer window. Now set inside the lock.unbound_script.go) and C (unbound_script.cc) layers to preventISOLATE_SCOPEfrom dereferencing NULL.Test plan
go vet ./...passesTestUnboundScriptRun_OnlyInTheSameIsolatepassesTestIsolate*andTestSnapshot*tests pass