-
Notifications
You must be signed in to change notification settings - Fork 79
Fix worker_threads teardown crash (SIGSEGV) and hang when node-api-dotnet is loaded in a Worker #487
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Vladimir Morozov (vmoroz)
merged 7 commits into
microsoft:main
from
GalaxiasKyklos:fix/aot-worker-teardown-segfault
Aug 5, 2026
+250
−1
Merged
Fix worker_threads teardown crash (SIGSEGV) and hang when node-api-dotnet is loaded in a Worker #487
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
f913197
Fix SIGSEGV when a worker_threads Worker that loaded node-api-dotnet …
GalaxiasKyklos 13c4362
Address review: use LibraryImport and cover macOS
GalaxiasKyklos f324805
Fix IDE0018 format check: inline dladdr out-variables per platform
GalaxiasKyklos acd6b01
Address review: gate pin to Linux and support pre-2.34 glibc
GalaxiasKyklos 93669dd
Add worker_threads teardown regression test for AOT host unload crash
GalaxiasKyklos db3edcc
Scope worker teardown regression test to the hosted host
GalaxiasKyklos d9f5371
Enhance PreventModuleUnload to support macOS, improve JSTsfnSynchroni…
jasongin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|
|
||
| // Regression test for a worker_threads teardown crash. | ||
| // | ||
| // When the native host is loaded ONLY inside a Worker (so no other reference keeps the | ||
| // module mapped) and the Worker is then terminated, Node.js unloads (dlclose) the addon | ||
| // while the worker's OS thread is still exiting. For a NativeAOT host that leaves a | ||
| // dangling pthread-key destructor, so the process crashes with SIGSEGV as the thread exits. | ||
| // NativeHost.PreventModuleUnload() pins the module to prevent that. This test fails (the | ||
| // child node process exits non-zero) if the crash regresses. | ||
| // | ||
| // This validates the hosted host module (Microsoft.JavaScript.NodeApi.node), which is what | ||
| // PreventModuleUnload() pins, so it runs under HostedClrTests only (excluded from | ||
| // NativeAotTests, whose generated module has a separate entry point). | ||
| // | ||
| // The binding is intentionally NOT loaded on the main thread: doing so would keep another | ||
| // module reference alive and mask the unload crash (which is why multi_instance.js cannot | ||
| // cover this case). | ||
|
|
||
| const assert = require('assert'); | ||
| const { Worker, isMainThread, parentPort } = require('worker_threads'); | ||
|
|
||
| if (isMainThread) { | ||
| const worker = new Worker(__filename); | ||
| worker.on('error', (err) => { throw err; }); | ||
| worker.once('message', (message) => { | ||
| assert.strictEqual(message, 'ready'); | ||
| // Let the worker settle, then tear it down. An unfixed host crashes during the | ||
| // worker thread's teardown after the module is unloaded. | ||
| setTimeout(async () => { | ||
| await worker.terminate(); | ||
| // Keep the process alive briefly so any teardown crash surfaces as a non-zero | ||
| // exit code instead of being skipped by an immediate process exit. | ||
| setTimeout(() => process.exit(0), 300); | ||
| }, 300); | ||
| }); | ||
| } else { | ||
| // Load the native host ONLY in the worker. | ||
| const binding = require('../common').binding; | ||
|
GalaxiasKyklos marked this conversation as resolved.
|
||
| assert.ok(binding); | ||
| parentPort.postMessage('ready'); | ||
| } | ||
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.