Child_process throw an Error: write EPIPE
Asked Answered
H

1

5

I just practise some node js code about child_process @the link My node version is V5.2.0 on windows 7.

// master.js
var cp=require("child_process");

var np=cp.fork("./console.js");               // line B

// block C
np.stdout.on("data",function(data){
   console.log("child process output:"+data);
});

np.stderr.on("data", function(err){
    console.log("child process output error:"+err);
});

np.on("close", function () {
    console.log("child process exit");
});

// end of block C



np.send({Hello:"world"});
np.on("message",function(msg){
    console.log("parent process got a msg:",msg);
});




// console.js

#!/usr/bin/env node

var aa=1;
console.log("The aa is :"+aa);


process.on("message", function (m) {
    console.log("child process got message:",m);
});

process.send({foo:"bar"});

1) I run above code ,I got the error: write EPIPE. I googled and I don't find any useful answer. I just a new to nodejs, I follow the official doc and do a little modification, then the sample code failes. I find that if I comment out the code in block C, the sample code is ok. So I wonder why the code throw error, if np.stdout/np.stderr listens to 'data'?

$ The aa is :1
events.js:142
      throw er; // Unhandled 'error' event
      ^

Error: write EPIPE
    at exports._errnoException (util.js:856:11)
    at process.target._send (internal/child_process.js:607:18)
    at process.target.send (internal/child_process.js:508:19)
    at Object.<anonymous> (D:\Practice\..\console.js:
11:9)
    at Module._compile (module.js:399:26)
    at Object.Module._extensions..js (module.js:406:10)
    at Module.load (module.js:345:32)
    at Function.Module._load (module.js:302:12)
    at Function.Module.runMain (module.js:431:10)
    at startup (node.js:141:18)

2) I modify the master.js code, run the code like below:

var cp=require("child_process");

var np=cp.spawn("node", ["./console.js"]);

np.send({Hello:"world"});
np.on("message",function(msg){
    console.log("parent process got a msg:",msg);
});

It throws an error:

np.send({Hello:"world"});
   ^

TypeError: np.send is not a function

I revisit the node js official doc, I don't find the spawn() and fork() are very different. So I wonder why np.send is not a function?

Are there some points the official doc doesn't mention?

Hild answered 10/5, 2016 at 12:5 Comment(0)
V
8

1/ About np.send not found method

child_process.send method is available when, the child is forked, or when its pipe are set to IPC

fork

When using child_process.fork() you can write to the child using child.send(message[, sendHandle][, callback]) and messages are received by a 'message' event on the child.

ipc

'ipc' - Create an IPC channel for passing messages/file descriptors between parent and child. A ChildProcess may have at most one IPC stdio file descriptor. Setting this option enables the ChildProcess.send() method. If the child writes JSON messages to this file descriptor, then this will trigger ChildProcess.on('message'). If the child is an Node.js program, then the presence of an IPC channel will enable process.send() and process.on('message').

var child = spawn('cat', ['index.js', {stdio: 'ipc'});

2/ About EPIPE

EPIPE means you're writing to a pipe or socket when the other end has terminated the connection.

This said, i found your observations suspicious because if you don t open the pipes, stdout && stderr && stdin objects of the child won t be populated. Thus it usually rise an error such TypeError: Cannot read property 'on' of null.

Then i double check the doc and seen that fork are very special, and i noticed that they don t provide any stdio option. But, it is said that it enables send method. My understanding is that fork method won t open any pipe and that only send method, on('message') mechanism are available.

This code works, with console.js left untouched

// master.js
var cp=require("child_process");

var np = cp.fork("./console.js");

np.on("close", function () {
    console.log("child process exit");
});


np.send({Hello:"world"});
np.on("message",function(msg){
    console.log("parent process got a msg:",msg);
});

To do something similar, but with spawn, we should take advantage of stdin to write, stdout or stderr to listen,

// master.js
var cp=require("child_process");

var np = cp.spawn(process.argv[0], ["./console.js"], {stdio: 'pipe'});

np.stdout.on("data",function(data){
   console.log("child process output:"+data);
});

np.stderr.on("data", function(err){
    console.log("child process output error:"+err);
});

np.on("close", function () {
    console.log("child process exit");
});

np.stdin.end(JSON.stringify({Hello:"world"}))

console.js

#!/usr/bin/env node

var aa=1;
console.log("The aa is :"+aa);


process.stdin.on("data", function (m) {
    console.log("child process got message:", m.toString());
});

process.stdout.write(JSON.stringify({foo:"bar"}))
// process.send({foo:"bar"});

That s it. I m not enable to give you precise answer about the specific error you provided.

I hope this helps.

Viridi answered 10/5, 2016 at 13:1 Comment(6)
I find that, I use spawn instead of fork, the code works. var np = cp.spawn('node', ["./child.js"], {stdio: ['inherit', 'inherit', 'inherit', 'ipc']});Hild
About the EPIPE error, could you please give more explanation?Hild
I can try, but unsure what to say. What are you interested in ?Viridi
The communication between parent and child thread on local computer, why the pipe closed? I googled and found most of the topic is about net/tcp, not much about local. Are there any tools that can monitor the closing?Hild
When the child exits, the pipe are closed. The child can also decide to close its pipes by its own, without quiting. You program can also close its pipes with the children without killing it.Viridi
So, you mean in my code, in the console.js, the child process was forked, then exited immediately? in the console.js, the child process has no long running statements like http.listening on a port, or stdin waiting for input?Hild

© 2022 - 2024 — McMap. All rights reserved.