Version: v8.10.0 Platform: Darwin Tapaswenis-MBP 16.7.0 Darwin Kernel Version 16.7.0:; root:xnu-3789.73.8~1/RELEASE_X86_64 x86_64
I'm trying to add a string to a child subprocess standard output. I want this code to work without editing the existing test case of main process.
const child = async (command, options, logger) =>
new Promise((resolve, reject) => {
const start = Date.now();
const child = child_process
.spawn(command, options)
.on('error', (err) => reject(err))
.on('exit', (code, signal) => {
const duration = Date.now() - start;
resolve({ code, signal, duration });
});
child.stdin.write('[some_string]');
child.stdout.pipe(logger.stream());
child.stderr.pipe(logger.stream());
});
I started with trying child.stdout.write
, with child.stdout.write('some_string')
I was able to log some_string in the child subprocess output, but my test failed with below error
events.js:183 throw er; // Unhandled 'error' event ^ Error: write EPIPE at _errnoException (util.js:992:11) at WriteWrap.afterWrite [as oncomplete] (net.js:864:14)
Now to find out why it is failing I checked if the EPIPE
is closed for writing with something like it wasn't.
process.stdout.on('error', function( err ) {
if (err.code == "EPIPE") {
process.exit(0);
}
});
I then logged the properties of child.stdout
turned out writable is false
. Same with stderr.write
for a child subprocess. Another option to write to a child subprocess is using child.stdin
, I logged its properties but it gave null
. Fine, but I was able to log the string with it.
child.stdout
properties, I can pipe but can't write as writable
is false? I didn't find any info about this here.
Socket {
connecting: false,
_hadError: false,
_handle:
Pipe {
writeQueueSize: 0,
owner: [Circular],
onread: [Function: onread],
reading: true },
_parent: null,
_host: null,
_readableState:
ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: null,
pipesCount: 0,
flowing: null,
ended: false,
endEmitted: false,
reading: true,
sync: false,
needReadable: true,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
destroyed: false,
defaultEncoding: 'utf8',
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
domain: null,
_events:
{ end: { [Function: bound onceWrapper] listener: [Function: onend] },
finish: [Function: onSocketFinish],
_socketEnd: [Function: onSocketEnd],
close: [Function] },
_eventsCount: 4,
_maxListeners: undefined,
_writableState:
WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: false,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: false,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 1,
prefinished: false,
errorEmitted: false,
bufferedRequestCount: 0,
corkedRequestsFree:
{ next: null,
entry: null,
finish: [Function: bound onCorkedFinish] } },
writable: false,
allowHalfOpen: false,
_bytesDispatched: 8,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
[Symbol(asyncId)]: 34495,
[Symbol(bytesRead)]: 0 }
Now, after adding child.stdin, in my test for the main process I do something like
const env = process.env;
process.env = { fake: 'environment' };
sinon.spy(child_process, 'spawn');
sinon.spy(process.stdout, 'write');
try {
await main_process.waitFor();
} catch (err) {
assert.ifError(err, 'failed');
}
const process_data = process.stdout.write.args[0][0];
process.stdout.write.restore();
assert.equal(
process_data,
'[Fri, 09 Feb 2018 21:57:55 GMT] [another_string] [895ab607-3767-4bbb-bd45-
2a3b341cbc46] something\n',
'abcd'
);
this process_data
is the main process data that I get(basically before adding .stdin
was able to get the main process logged data. Now for some reason this has become undefined. Basically when I logged properties of process.stdout.write
, args is blank, so it is not fetching the args.
Why writing to .stdin
on a child subprocess is affecting the process.stdout.write
args of main process? What am I missing here? would appreciate any pointers or even a link if I'm missing something here.
This project I'm working on is open source, can share the whole code if that helps.