Description
- Version: At least v6.9.1 and v8.5.0
- Platform: Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 PDT 2015; x86_64
I'm trying to implement a sort of PassThrough
-style stream that can be used as mock stdio for ChildProcess.spawn()
. PassThrough
itself isn't appropriate because it doesn't have a file descriptor. So I'm doing this by creating a socket that speaks to an echo server. What I'm finding is that the server receives the data and successfully pipes it, but the passthrough socket never seems to receive it.
I've poked around the node internals a bit to figure-out why, but I don't have much to share at this time. It looks like spawn()
may create another socket that's readable and not writable, and uses the socket I passed as its handle [here]. But my socket remains readable and writable as I would expect, so I still can't explain the behavior!
Possibly related to #9413. Here's some code to reproduce the issue and play with.
'use strict';
const ChildProcess = require('child_process');
const Net = require('net');
const makePassThrough = (cb) => {
const srv = Net.createServer((sock) => {
sock.on('data', (data) => console.log('server sock saw data:', data.toString()));
sock.once('close', () => console.log('server sock closed'));
sock.once('end', () => console.log('server sock ended'));
sock.once('error', (err) => console.log('server sock errored', err));
sock.once('timeout', () => console.log('server sock timed-out'));
sock.pipe(sock);
});
srv.once('close', () => console.log('server closed'));
srv.once('error', cb);
srv.listen(() => {
const sock = new Net.Socket();
sock.once('close', () => console.log('client sock closed'));
sock.once('end', () => console.log('client sock ended'));
sock.once('error', (err) => console.log('client sock errored', err));
sock.once('timeout', () => console.log('client sock timed-out'));
sock.once('error', cb);
sock.connect(srv.address().port, () => cb(null, sock));
});
};
makePassThrough((err, stdout) => {
if (err) {
throw err;
}
stdout.on('data', (data) => console.log('subproc stdout saw data:', data.toString()));
const subproc = ChildProcess.spawn('echo', ['is anybody out there?'], {
stdio: ['ignore', stdout, 'ignore']
});
subproc.on('close', process.exit);
});
/* Program outputs the following,
$ node index.js
server sock saw data: is anybody out there?
# Does not exit
*/
For my purposes I'm all set– I can use stdio: 'pipe'
and pipe the process's stdio thru actual passthrough streams. This is still a curiosity, though!