diff --git a/lib/internal/bootstrap/switches/is_not_main_thread.js b/lib/internal/bootstrap/switches/is_not_main_thread.js index 03aa7c3ebe1..6fa30aec748 100644 --- a/lib/internal/bootstrap/switches/is_not_main_thread.js +++ b/lib/internal/bootstrap/switches/is_not_main_thread.js @@ -33,11 +33,22 @@ process.removeListener('removeListener', stopListeningIfSignal); const { createWorkerStdio, + kStdioWantsMoreDataCallback, } = require('internal/worker/io'); let workerStdio; function lazyWorkerStdio() { - return workerStdio ??= createWorkerStdio(); + if (workerStdio === undefined) { + workerStdio = createWorkerStdio(); + process.on('exit', flushSync); + } + + return workerStdio; +} + +function flushSync() { + workerStdio.stdout[kStdioWantsMoreDataCallback](); + workerStdio.stderr[kStdioWantsMoreDataCallback](); } function getStdout() { return lazyWorkerStdio().stdout; } diff --git a/lib/internal/worker/io.js b/lib/internal/worker/io.js index 42b8845cec6..2b28c6a2487 100644 --- a/lib/internal/worker/io.js +++ b/lib/internal/worker/io.js @@ -292,9 +292,13 @@ class WritableWorkerStdio extends Writable { chunks: ArrayPrototypeMap(chunks, ({ chunk, encoding }) => ({ chunk, encoding })), }); - ArrayPrototypePush(this[kWritableCallbacks], cb); - if (this[kPort][kWaitingStreams]++ === 0) - this[kPort].ref(); + if (process._exiting) { + cb(); + } else { + ArrayPrototypePush(this[kWritableCallbacks], cb); + if (this[kPort][kWaitingStreams]++ === 0) + this[kPort].ref(); + } } _final(cb) { diff --git a/test/parallel/test-worker-stdio-flush-inflight.js b/test/parallel/test-worker-stdio-flush-inflight.js new file mode 100644 index 00000000000..34b81152811 --- /dev/null +++ b/test/parallel/test-worker-stdio-flush-inflight.js @@ -0,0 +1,24 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { Worker, isMainThread } = require('worker_threads'); + +if (isMainThread) { + const w = new Worker(__filename, { stdout: true }); + const expected = 'hello world'; + + let data = ''; + w.stdout.setEncoding('utf8'); + w.stdout.on('data', (chunk) => { + data += chunk; + }); + + w.on('exit', common.mustCall(() => { + assert.strictEqual(data, expected); + })); +} else { + process.stdout.write('hello'); + process.stdout.write(' '); + process.stdout.write('world'); + process.exit(0); +} diff --git a/test/parallel/test-worker-stdio-flush.js b/test/parallel/test-worker-stdio-flush.js new file mode 100644 index 00000000000..e52e721fc69 --- /dev/null +++ b/test/parallel/test-worker-stdio-flush.js @@ -0,0 +1,25 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { Worker, isMainThread } = require('worker_threads'); + +if (isMainThread) { + const w = new Worker(__filename, { stdout: true }); + const expected = 'hello world'; + + let data = ''; + w.stdout.setEncoding('utf8'); + w.stdout.on('data', (chunk) => { + data += chunk; + }); + + w.on('exit', common.mustCall(() => { + assert.strictEqual(data, expected); + })); +} else { + process.on('exit', () => { + process.stdout.write(' '); + process.stdout.write('world'); + }); + process.stdout.write('hello'); +}