-
-
Notifications
You must be signed in to change notification settings - Fork 33.8k
Description
Version: 9.0.0-pre
Platform: macOS 10.x (seen on 10.10, 10.11, and 10.12)
Subsystem: cluster child_process
A workaround/fix was introduced to test-cluster-send-handle-large-payload in #14780 so that it wouldn't time out on macOS from time to time.
It's not clear if this behavior is a bug in the test, a bug in Node.js, a bug in macOS, or simply not a bug at all.
dtruss -f output
-
Success: https://gist.github.com/Trott/e32e1a48c84a9fdba09177e90bda05d4
-
Failure: https://gist.github.com/Trott/fb77e052ff369e33d1b18f5ad9492ba9 (terminated with cntl-c after it hung for a while, if that matters)
Additional info from #14747
When this times out, the process.send() in the subprocess is getting called, but the message event on worker is not being emitted (or at least the listener is not being invoked).
If I add a callback to process.send(), it never indicates an error in this test, whether the test succeeds or times out.
Judging from #6767, process.send() may be fire-and-forget. Maybe the message gets received and maybe not.
I don't know why macOS would be more susceptible to missing the message than anything else. If this is not-a-bug behavior, I guess we can add a retry. If this is a bug... ¯(ツ)/¯
The .send() from the parent process to the subprocess never seems to fail.
Code from version of test without the fix/workaround:
'use strict';
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');
const net = require('net');
const payload = 'a'.repeat(800004);
if (cluster.isMaster) {
const server = net.createServer();
server.on('connection', common.mustCall((socket) => socket.unref()));
const worker = cluster.fork();
worker.on('message', common.mustCall(({ payload: received }, handle) => {
assert.strictEqual(payload, received);
assert(handle instanceof net.Socket);
server.close();
handle.destroy();
}));
server.listen(0, common.mustCall(() => {
const port = server.address().port;
const socket = new net.Socket();
socket.connect(port, (err) => {
assert.ifError(err);
worker.send({ payload }, socket);
});
}));
} else {
process.on('message', common.mustCall(({ payload: received }, handle) => {
assert.strictEqual(payload, received);
assert(handle instanceof net.Socket);
process.send({ payload }, handle);
// Prepare for a clean exit.
process.channel.unref();
handle.unref();
}));
}/cc @addaleax