Skip to content

libuv: fix kqueue assertion crash on Darwin#523677

Draft
mkg20001 wants to merge 2 commits into
NixOS:masterfrom
mkg20001:nodejs-kqueue-ebadf-fix
Draft

libuv: fix kqueue assertion crash on Darwin#523677
mkg20001 wants to merge 2 commits into
NixOS:masterfrom
mkg20001:nodejs-kqueue-ebadf-fix

Conversation

@mkg20001

@mkg20001 mkg20001 commented May 24, 2026

Copy link
Copy Markdown
Member

Description

Fixes a SIGABRT (Abort trap: 6) crash caused by libuv's kqueue poller asserting errno == EINTR after kevent() fails.

kevent() can also return EBADF (closed fd still in changelist) or ENOENT (fd removed between changelist submit and kevent call). This triggers most reliably with Node.js 24.15.0+ running pnpm with large package sets (1400+ packages) inside the Nix build sandbox, due to changes in ArrayBuffer transfer semantics (nodejs/node#61372) that alter file descriptor lifecycle timing.

The assertion (src/unix/kqueue.c:279) is present in libuv 1.52.1 (latest). The patch relaxes it to accept EBADF and ENOENT alongside EINTR — all transient conditions that the existing retry logic already handles correctly.

Root cause chain:

  1. Node.js 24.15.0 changed ArrayBuffer transfer behavior
  2. This alters how native addons (SQLite bindings in pnpm's store) manage memory/FD lifecycle
  3. An FD gets closed while still registered in kqueue's changelist
  4. kevent() returns EBADF instead of EINTR
  5. libuv's strict assert(errno == EINTR) fires → SIGABRT

Upstream references:

Assisted-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

Things done

@nixpkgs-branch-check nixpkgs-branch-check Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR's base branch is set to master, but this PR causes 37992 rebuilds.
It is therefore considered a mass rebuild.
Please change the base branch to the right base branch for your changes (probably staging).

@nixpkgs-ci nixpkgs-ci Bot added 10.rebuild-darwin: 501+ This PR causes many rebuilds on Darwin and should normally target the staging branches. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux. 10.rebuild-darwin: 5001+ This PR causes many rebuilds on Darwin and must target the staging branches. 6.topic: nodejs Node.js is a free, open-source, cross-platform JavaScript runtime environment labels May 24, 2026
libuv's kqueue poller (`uv__io_poll` in `kqueue.c`) asserts that when
`kevent()` returns -1, `errno` must be `EINTR`. However, `kevent()` can
also return `EBADF` when a file descriptor is closed while still in the
kqueue changelist, or `ENOENT` when removed between changelist submit
and the kevent call.

This surfaces as an `Abort trap: 6` (SIGABRT) on Darwin when running
pnpm in the Nix build sandbox with Node.js 24.15.0+, due to changes in
ArrayBuffer transfer semantics that alter FD lifecycle timing.

The fix relaxes the assertion to accept EBADF and ENOENT in addition to
EINTR, all of which are transient conditions that the existing retry
logic already handles correctly.

Reproducer: `pnpm install --force` with 1400+ packages in nix sandbox.
Upstream: libuv/libuv#976

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mkg20001 mkg20001 force-pushed the nodejs-kqueue-ebadf-fix branch from 4bba260 to 991253a Compare May 24, 2026 17:26
@mkg20001 mkg20001 changed the title nodejs{22,24,26}: fix libuv kqueue assertion crash on Darwin libuv: fix kqueue assertion crash on Darwin May 24, 2026
@nixpkgs-ci nixpkgs-ci Bot removed the 6.topic: nodejs Node.js is a free, open-source, cross-platform JavaScript runtime environment label May 24, 2026
Now that libuv's kqueue assertion is fixed, openclaw no longer needs
the nodejs_22 workaround for pnpm and can use pnpm_11 with its default
Node.js (24.15.0).

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@nixpkgs-ci nixpkgs-ci Bot added 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 10.rebuild-linux: 1 This PR causes 1 package to rebuild on Linux. and removed 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux. labels May 24, 2026
@ofborg ofborg Bot added the 6.topic: darwin Running or building packages on Darwin label May 25, 2026
@nixpkgs-ci nixpkgs-ci Bot added the 2.status: merge conflict This PR has merge conflicts with the target branch label Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2.status: merge conflict This PR has merge conflicts with the target branch 6.topic: darwin Running or building packages on Darwin 10.rebuild-darwin: 501+ This PR causes many rebuilds on Darwin and should normally target the staging branches. 10.rebuild-darwin: 5001+ This PR causes many rebuilds on Darwin and must target the staging branches. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 10.rebuild-linux: 1 This PR causes 1 package to rebuild on Linux.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant