1'use strict'; 2const common = require('../common'); 3 4// Before https://github.com/nodejs/node/pull/2847 a child process trying 5// (asynchronously) to use the closed channel to it's creator caused a segfault. 6 7const assert = require('assert'); 8const cluster = require('cluster'); 9const net = require('net'); 10 11if (!cluster.isMaster) { 12 // Exit on first received handle to leave the queue non-empty in master 13 process.on('message', function() { 14 process.exit(1); 15 }); 16 return; 17} 18 19const server = net 20 .createServer(function(s) { 21 if (common.isWindows) { 22 s.on('error', function(err) { 23 // Prevent possible ECONNRESET errors from popping up 24 if (err.code !== 'ECONNRESET') throw err; 25 }); 26 } 27 setTimeout(function() { 28 s.destroy(); 29 }, 100); 30 }) 31 .listen(0, function() { 32 const worker = cluster.fork(); 33 34 worker.on('error', function(err) { 35 if ( 36 err.code !== 'ECONNRESET' && 37 err.code !== 'ECONNREFUSED' && 38 err.code !== 'EMFILE' 39 ) { 40 throw err; 41 } 42 }); 43 44 function send(callback) { 45 const s = net.connect(server.address().port, function() { 46 worker.send({}, s, callback); 47 }); 48 49 // https://github.com/nodejs/node/issues/3635#issuecomment-157714683 50 // ECONNREFUSED or ECONNRESET errors can happen if this connection is 51 // still establishing while the server has already closed. 52 // EMFILE can happen if the worker __and__ the server had already closed. 53 s.on('error', function(err) { 54 if ( 55 err.code !== 'ECONNRESET' && 56 err.code !== 'ECONNREFUSED' && 57 err.code !== 'EMFILE' 58 ) { 59 throw err; 60 } 61 }); 62 } 63 64 worker.process.once( 65 'close', 66 common.mustCall(function() { 67 // Otherwise the crash on `channel.fd` access may happen 68 assert.strictEqual(worker.process.channel, null); 69 server.close(); 70 }) 71 ); 72 73 worker.on('online', function() { 74 send(function(err) { 75 assert.ifError(err); 76 send(function(err) { 77 // Ignore errors when sending the second handle because the worker 78 // may already have exited. 79 if (err && err.code !== 'ERR_IPC_CHANNEL_CLOSED' && 80 err.code !== 'ECONNRESET' && 81 err.code !== 'ECONNREFUSED' && 82 err.code !== 'EMFILE') { 83 throw err; 84 } 85 }); 86 }); 87 }); 88 }); 89