The process never ends when piping the stdin to a child process
IonicaBizau opened this issue · 10 comments
Initially I asked this on StackOverflow, but looks like a bug (nodejs/node-v0.x-archive#9190). Post follows:
I'm using spawn
to create a child process and pipe data:
child process | parent process (main)
---------------------------------------
stdout -----> process.stdout
stderr -----> process.stderr
stdin <----- process.stdin
The problem is that when piping the process.stdin
to the child process stdin
, the main process is not ended when the child process is finished.
The code looks like this (not a really good example because ps
does not use stdin
data, I guess):
var Spawn = require("child_process").spawn;
var ps = Spawn("ps");
process.stdin.pipe(ps.stdin);
ps.stdout.pipe(process.stdout);
ps.stderr.pipe(process.stderr);
If I remove the process.stdin.pipe(ps.stdin)
line, the main process is ended, but the stdin
data is not piped anymore.
Why isn't the main process ended when the ps
child process is ended? How can I solve this problem?
An ugly solution would be:
ps.on("close", process.exit.bind(process));
I don't like this, because I don't really want to force the main process to be closed, but I want to be closed naturally (e.g. having setTimeout(function(){}, 1000)
you wait 1000ms and then the process ends).
I tried to ps.stdin.close()
in ps.on("close", cb)
. It didn't work... 😢
Your example works fine with a command that uses stdin like cat
:
var Spawn = require('child_process').spawn;
var ps = Spawn('cat');
process.stdin.pipe(ps.stdin);
ps.stdout.pipe(process.stdout);
ps.stderr.pipe(process.stderr);
% echo "abc" | node test.js
abc
We may need more information about the context of your problem, in order to help further.
Does ps
actually consume the stdin that is piped to it?
Edit: Maybe ps
doesn't close when it's being piped to unless you tell it to?
@targos Interesting! If I pipe data to the process, it's closed:
The code is:
var Spawn = require("child_process").spawn;
var ps = Spawn('cat');
process.stdin.pipe(ps.stdin);
ps.stdout.pipe(process.stdout);
ps.stderr.pipe(process.stderr);
ps.on("close", function () {
console.log("Closed");
});
And the result is:
$ echo "foo" | node index.js
foo
Closed
If I don't pipe anything, the process is not closed, which is fine in this case because the child process is not closed (it still listens for data).
However, in the ps
case (just replace cat
with ps
in the code above) there is a strange behavior:
$ node index.js # This does not close the main process, even the child process is closed
PID TTY TIME CMD
9021 pts/23 00:00:00 node
9026 pts/23 00:00:00 ps
30815 pts/23 00:00:00 bash
Closed
^C
$ echo "foo" | node index.js
PID TTY TIME CMD
12728 pts/23 00:00:00 node
12733 pts/23 00:00:00 ps
30815 pts/23 00:00:00 bash
Closed
$ echo "foo" | node index.js
PID TTY TIME CMD
12735 pts/23 00:00:00 node
12740 pts/23 00:00:00 ps
30815 pts/23 00:00:00 bash
Closed
$ echo "foo" | node index.js
events.js:85
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at exports._errnoException (util.js:746:11)
at WriteWrap.afterWrite (net.js:766:14)
Why does the EPIPE error appears randomly?
We may need more information about the context of your problem, in order to help further.
I'm happy to provide more information, just ask me. 😸
@Fishrock123 Yeah, probable it doesn't use the stdin data, but the child process is closed -- while the parent still remains alive.
I'm not sure, but I guess we could say that if the stdin data is not consumed in the child process, then the main process never ends, even the child process does.
Any feedback on this?
@IonicaBizau hmmm, that looks like #947?
(Which fwiw, is a pretty tricky issue.)
@Fishrock123 Ah, actually, yes. Thanks.
I'm still seeing this issue in Node v10.3.0, was this supposed to be resolved in #947?
The issue being that if you create a child process and pipe the parent's stdin
to the child
, the parent never dies even if the child does.
I'm a bit confused by the current state of this, you seem to show this is not a problem with cat
, but is with ps
, in which case the problem isn't with the node parent but with the behaviour of the non-node child, isn't it?
ps
is special, and has odd behaviour wrt. to stdin, cf #24327 (comment).
Can you provide a small self-contained example and a description of how the examples behaviour differs from your expectation?