worker_threads Worker exit aborts (SIGABRT) when a native addon (fsevents) has an in-flight napi_threadsafe_function — napi_release_threadsafe_function / uv_mutex_lock
还没有人认领这个 Issue。
- 主要语言
- JavaScript
- 星标
- 122k
- 派生
- 37.4k
- 平均合并
- 4 天 3 小时
- 30 天内合并 PR
- 272
描述
Version
v24.15.0 through v24.19.0 (tested v24.15.0, v24.16.0, v24.19.0 — all crash).
Does NOT reproduce on v24.11.0 or v24.11.1.
Platform
macOS 15.6.1 (24G90), Apple Silicon (arm64)
Subsystem
worker_threads, N-API (napi_threadsafe_function)
What steps will reproduce the bug?
Minimal repro repo: https://github.com/mastoj/node24-fsevents-worker-threads-abort
npm installnode main.mjs 50
main.mjs spawns 50 worker_threads.Workers sequentially. Each worker
(worker.mjs) does:
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const fsevents = require("fsevents");
fsevents.watch(process.argv[2], () => {});
setTimeout(() => process.exit(0), 5);
i.e. it starts a native fsevents watch (which registers a
napi_threadsafe_function under the hood) and exits the worker shortly
after, without explicitly stopping the watcher first.
How often does it reproduce? Is there a required condition?
100% reproducible on Node.js v24.15.0+ on macOS. Crashes on the very first
worker. 0% reproducible on Node.js v24.11.0/v24.11.1 (ran 50 workers cleanly).
What is the expected behavior?
All workers start, watch, and exit cleanly with code 0:
worker 0 exited with code 0
...
worker 49 exited with code 0
done, no crash across 50 workers
(This is what actually happens on v24.11.0.)
What do you see instead?
The whole process aborts with SIGABRT (exit code 134) on the very first
worker — before any of the console.log lines are even printed, since the
abort takes down the entire process (all worker threads share one OS
process).
$ node main.mjs 50
Abort trap: 6
$ echo $?
134
macOS crash reporter consistently shows the same stack trace on the
"WorkerThread":
__pthread_kill
pthread_kill
abort
uv_mutex_lock
napi_release_threadsafe_function
fse_instance_destroy
napi_env__::CallIntoModule<...>
node_napi_env__::CallFinalizer(void (*)(napi_env__*, void*, void*), void*, void*)
v8impl::Reference::Finalize()
node_napi_env__::DeleteMe()
node::Environment::CloseHandle<...>
uv_run
node::Environment::RunCleanup()
node::FreeEnvironment(node::Environment*)
node::worker::Worker::Run()
node::worker::Worker::StartThread(...)::$_0::__invoke(void*)
_pthread_start
thread_start
i.e. during worker-thread Environment teardown, napi_release_threadsafe_function
attempts uv_mutex_lock while finalizing fsevents' native threadsafe
function, and this ends in abort() instead of a clean/graceful teardown.
Additional context
This was originally found as a crash inside a real-world Next.js 16.3.0
monorepo build (next build --turbopack), where Next's build worker threads
transitively load fsevents (via chokidar/watchpack) and exit shortly
after doing their work. The exact same crash signature (same stack trace)
was observed across 15+ independent crash reports collected via macOS's
crash reporter during real builds, before being reduced to this minimal,
Next.js-free, fsevents-only reproduction.
It doesn't reproduce in a fresh create-next-app project (which doesn't
happen to have an active fsevents watcher inside its build workers) —
only projects where a native addon with an in-flight
napi_threadsafe_function is active in a worker thread at worker-exit
time.
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从最小复现的 main.mjs 和 worker.mjs 开始:运行 npm install 和 node main.mjs 50,然后将 v24.11.1 与 v24.15.0 或更高版本进行比较。跟踪 stack 中显示的 worker teardown 路径,尤其是 napi_release_threadsafe_function 和 Environment::RunCleanup。完成标准是全部 50 个 worker 都以代码 0 退出,且没有 SIGABRT。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- javascript, node.js
- 领域
- backend, operating-systems
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 冷清
- 描述清晰度
- 基本清楚
- 新手友好度
- 48/100