diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 070acd70b7a785..2583d5d36208cf 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -387,6 +387,9 @@ ChildProcess.prototype.spawn = function(options) { // The stream is already cloned and piped, thus close it. if (stream.type === 'wrap') { stream.handle.close(); + if (stream._stdio && stream._stdio instanceof EventEmitter) { + stream._stdio.emit('close'); + } continue; } @@ -946,7 +949,8 @@ function _validateStdio(stdio, sync) { acc.push({ type: 'wrap', wrapType: getHandleWrapType(handle), - handle: handle + handle: handle, + _stdio: stdio }); } else if (isArrayBufferView(stdio) || typeof stdio === 'string') { if (!sync) { diff --git a/test/parallel/test-child-process-server-close.js b/test/parallel/test-child-process-server-close.js new file mode 100644 index 00000000000000..f03203cdab0e7e --- /dev/null +++ b/test/parallel/test-child-process-server-close.js @@ -0,0 +1,20 @@ +'use strict'; + +const common = require('../common'); +const { spawn } = require('child_process'); +const net = require('net'); + +const server = net.createServer((conn) => { + conn.on('close', common.mustCall()); + + spawn(process.execPath, ['-v'], { + stdio: ['ignore', conn, 'ignore'] + }).on('close', common.mustCall()); +}).listen(common.PIPE, () => { + const client = net.connect(common.PIPE, common.mustCall()); + client.on('data', () => { + client.end(() => { + server.close(); + }); + }); +});