node/test/parallel/test-child-process-fork-closed-channel-segfault.js
Rich Trott 4f0ab76b6c test: use error code rather than message in test
Use err.code checking instead of err.message checking in
test-child-process-fork-closed-channel-segfault.

PR-URL: https://github.com/nodejs/node/pull/20859
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
2018-05-21 20:51:46 -07:00

76 lines
2.1 KiB
JavaScript

'use strict';
const common = require('../common');
// Before https://github.com/nodejs/node/pull/2847 a child process trying
// (asynchronously) to use the closed channel to it's creator caused a segfault.
const assert = require('assert');
const cluster = require('cluster');
const net = require('net');
if (!cluster.isMaster) {
// Exit on first received handle to leave the queue non-empty in master
process.on('message', function() {
process.exit(1);
});
return;
}
const server = net
.createServer(function(s) {
if (common.isWindows) {
s.on('error', function(err) {
// Prevent possible ECONNRESET errors from popping up
if (err.code !== 'ECONNRESET') throw err;
});
}
setTimeout(function() {
s.destroy();
}, 100);
})
.listen(0, function() {
const worker = cluster.fork();
function send(callback) {
const s = net.connect(server.address().port, function() {
worker.send({}, s, callback);
});
// https://github.com/nodejs/node/issues/3635#issuecomment-157714683
// ECONNREFUSED or ECONNRESET errors can happen if this connection is
// still establishing while the server has already closed.
// EMFILE can happen if the worker __and__ the server had already closed.
s.on('error', function(err) {
if (
err.code !== 'ECONNRESET' &&
err.code !== 'ECONNREFUSED' &&
err.code !== 'EMFILE'
) {
throw err;
}
});
}
worker.process.once(
'close',
common.mustCall(function() {
// Otherwise the crash on `channel.fd` access may happen
assert.strictEqual(worker.process.channel, null);
server.close();
})
);
worker.on('online', function() {
send(function(err) {
assert.ifError(err);
send(function(err) {
// Ignore errors when sending the second handle because the worker
// may already have exited.
if (err && err.code !== 'ERR_IPC_CHANNEL_CLOSED') {
throw err;
}
});
});
});
});