Repository navigation
fix(go-port,node-loader): fix macOS Go port race conditions and deadlocks (#942) - #963
Open
TheDoomBoy-jab wants to merge 2 commits into
Open
TheDoomBoy-jab wants to merge 2 commits into
TheDoomBoy-jab wants to merge 2 commits into
Conversation
added 2 commits
November 14, 2026 11:05
TheDoomBoy-jab
force-pushed
the
fix/go-port-macos-race-conditions
branch
from
November 14, 2026 05:35
0c017a5 to
1bc5392
Compare
This branch has not been deployed
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
This PR addresses the race conditions, crashes, and shutdown deadlocks observed when running the Go port test suite and benchmarks on macOS (Darwin).
Motive & Root Causes
Reason: no LC_RPATH's found):On macOS, System Integrity Protection (SIP) automatically strips
DYLD_LIBRARY_PATHfrom spawned child processes. BecauseCGO_LDFLAGSonly passed-L${PROJECT_OUTPUT_DIR} -lmetacall, the compiled Go test binary lacked an embedded runpath tolibmetacall.dylib.future_node_interface_delete:future_node_interface_deleteusesloader_impl_async_safe_typeon the stack to wait for the V8 thread to run the deletion callback viauv_cond_wait(&cond, &mutex). On macOS, Go's runtime routinely dispatchesSIGURGsignals across threads for non-cooperative goroutine preemption. Becauseuv_cond_waitwas not wrapped in a predicate loop,SIGURGinduced spurious condition wakeups, causing the caller stack to unwind and destroy theuv_mutex_tbefore the V8 thread executeduv_mutex_lock(triggering an abort trap).In
node_loader_impl_napi_to_value,node_future->promise_refwas not initialized prior tofuture_create, and a failure invalue_create_futuredid not clean upf.TestGoRoutineLeaks:TestGoRoutineLeaksexplicitly callsDestroy()(metacall_destroy()) to test concurrent queue shutdown. In Go,go testruns unit tests before benchmarks in the same process. Terminating the runtime inTestGoRoutineLeaksleft subsequentBenchmarkNodeJSruns failing with shutdown errors.Approach & Changes
source/ports/go_port/CMakeLists.txt:-Wl,-rpath,${PROJECT_OUTPUT_DIR}toGO_PORT_CGO_LDFLAGSso the Go test binary embeds the rpath tolibmetacall.dylib.goroutine_leaksprofile generation on macOS.source/loaders/node_loader/source/node_loader_impl.cpp:while (!completed) { uv_cond_wait(&cond, &mutex); }) andcompleted = trueflag inloader_impl_async_safe_typeto eliminate spurious wakeups from OS signals (SIGURG).node_future->promise_ref = nullptrand loader references prior tofuture_create, and destroyfon allocation failure.source/ports/go_port/source/go_port_test.go:TestGoRoutineLeaksin a dedicated subprocess (GO_PORT_SUBPROCESS_LEAKS=1), preventing itsDestroy()invocation from terminating the parent process's runtime.TestGoRoutineLeaks,BenchmarkNodeJSSequential, andBenchmarkNodeJSParallelon Darwin by removing theruntime.GOOS == "darwin"skips.