From 14c431b9eb58c549b59f2e0e8e3847017e0deea7 Mon Sep 17 00:00:00 2001 From: Dylan Conway Date: Sat, 8 Aug 2026 07:09:28 -0700 Subject: [PATCH 1/2] test(napi): keep node's stdout in program order in the napi-app fixture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit napi.test.ts compares the stdout of `node main.js ` and `bun main.js `. On Linux the node side intermittently emitted its console.log lines after all of the addon's printf output, failing `napi_get_value_string_* > behaves like node on edge cases`. - Node's stdout is asynchronous when it is a pipe on POSIX: once a write() returns EAGAIN, libuv queues that console.log and every later one until the event loop runs, while printf keeps writing to fd 1 directly. Make node's stdout blocking in main.js so JS and native output cannot reorder. - The EAGAIN came from BlockingStdoutScope: both runtimes start with stdout unbuffered, and glibc's setvbuf(stdout, NULL, _IOFBF, 8192) keeps the existing 1-byte buffer, so each scope produced thousands of 1–2 byte writes that exhausted the AF_UNIX socketpair's send buffer by skb overhead. Give it a real buffer and restore _IONBF afterwards. No-Verification-Needed: test-fixture-only change --- test/napi/napi-app/main.js | 5 +++++ test/napi/napi-app/utils.h | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/test/napi/napi-app/main.js b/test/napi/napi-app/main.js index 9c11801727f4..8d0b3c2e79bb 100644 --- a/test/napi/napi-app/main.js +++ b/test/napi/napi-app/main.js @@ -1,3 +1,8 @@ +// Node writes to a piped stdout asynchronously on POSIX: after one EAGAIN every +// console.log is queued until the event loop runs while the addons' printf keeps +// writing to the fd directly. Make it blocking so output stays in program order. +if (!process.isBun) process.stdout._handle?.setBlocking?.(true); + const tests = require("./module"); if (process.argv[2] === "self") { console.log( diff --git a/test/napi/napi-app/utils.h b/test/napi/napi-app/utils.h index 0711999a329e..3a0f69854b20 100644 --- a/test/napi/napi-app/utils.h +++ b/test/napi/napi-app/utils.h @@ -13,18 +13,21 @@ class BlockingStdoutScope { BlockingStdoutScope() { original = fcntl(1, F_GETFL); fcntl(1, F_SETFL, original & ~O_NONBLOCK); - setvbuf(stdout, nullptr, _IOFBF, 8192); fflush(stdout); + // Both runtimes start with stdout unbuffered. glibc keeps the existing + // 1-byte buffer when setvbuf is given a null buffer, so pass a real one. + setvbuf(stdout, buffer, _IOFBF, sizeof(buffer)); } ~BlockingStdoutScope() { fflush(stdout); fcntl(1, F_SETFL, original); - setvbuf(stdout, nullptr, _IOLBF, 0); + setvbuf(stdout, nullptr, _IONBF, 0); } private: int original; + inline static char buffer[8192]; }; #endif From b1b09bd02feeb3d4257eeec1ca1f89e32665fd61 Mon Sep 17 00:00:00 2001 From: Dylan Conway Date: Sat, 8 Aug 2026 11:49:38 -0700 Subject: [PATCH 2/2] ci: retrigger