admin管理员组

文章数量:1313054

I am attempting to fork a node.js module as a child process per the example posted on this stackoverflow question. The fork itself works, but the problem I am running into is that node is attempting to add the .on('data') and .on('exit') before the fork('./DaemonSerial.js' populates tChild

var fork = require('child_process').fork;

// Start Serial Daemon/s
var tChild = fork('./DaemonSerial.js', [], {
  stdio: 'pipe'
});
tChild.stdin.on('data', function(data) {
  // output from the child process
  console.log("./DaemonSerial.js >>> " + data)
 });
EdgeMaster.Children[tChild.pid] = tChild;
tChild.on('exit', function(d) {
    console.log("./DaemonSerial.js >>> "+ tChild.pid + ' Exited:'+ d);
    delete EdgeMaster.Children[tChild.pid]
 });

I have also run into this problem elsewhere, and am reasonable sure there should be a method of enforcing a do THIS then THAT type of functionality even when the function itself does not have a callback. child_process.fork(modulePath, [args], [options]) on nodejs/api/child_process.html does not list a callback.

ideas?

EDIT: I wrote a new script forktest.js to rule out any possibility that other parts of my script might be causing the issue. forktest.js is exactly as follows:

var fork = require('child_process').fork;

var ForkDict = {};

function forkit(aPath){
    tChild = fork( aPath, [], {stdio: 'pipe'});
    ForkDict[tChild.pid] = tChild;
    ForkDict[tChild.pid].path = aPath;
    tChild.stdout.on('data', function(data) {
        // output from the child process
        console.log( this.path +'>>> '+ data);
     }.bind(this));
    tChild.on('exit', function(d) {
        console.log( this.path +'>>> Exited:'+ d);
        delete ForkDict[tChild.pid]
     }.bind(this));
}

forkit('./DaemonSerial.js');

the error from the console reads as follows:

pi@raspberrypi ~ $ node forktest.js

/home/pi/forktest.js:9
    tChild.stdout.on('data', function(data) {
                  ^
TypeError: Cannot call method 'on' of null
    at forkit (/home/pi/forktest.js:9:19)
    at Object.<anonymous> (/home/pi/forktest.js:19:1)
    at Module._pile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:901:3

I am attempting to fork a node.js module as a child process per the example posted on this stackoverflow question. The fork itself works, but the problem I am running into is that node is attempting to add the .on('data') and .on('exit') before the fork('./DaemonSerial.js' populates tChild

var fork = require('child_process').fork;

// Start Serial Daemon/s
var tChild = fork('./DaemonSerial.js', [], {
  stdio: 'pipe'
});
tChild.stdin.on('data', function(data) {
  // output from the child process
  console.log("./DaemonSerial.js >>> " + data)
 });
EdgeMaster.Children[tChild.pid] = tChild;
tChild.on('exit', function(d) {
    console.log("./DaemonSerial.js >>> "+ tChild.pid + ' Exited:'+ d);
    delete EdgeMaster.Children[tChild.pid]
 });

I have also run into this problem elsewhere, and am reasonable sure there should be a method of enforcing a do THIS then THAT type of functionality even when the function itself does not have a callback. child_process.fork(modulePath, [args], [options]) on nodejs/api/child_process.html does not list a callback.

ideas?

EDIT: I wrote a new script forktest.js to rule out any possibility that other parts of my script might be causing the issue. forktest.js is exactly as follows:

var fork = require('child_process').fork;

var ForkDict = {};

function forkit(aPath){
    tChild = fork( aPath, [], {stdio: 'pipe'});
    ForkDict[tChild.pid] = tChild;
    ForkDict[tChild.pid].path = aPath;
    tChild.stdout.on('data', function(data) {
        // output from the child process
        console.log( this.path +'>>> '+ data);
     }.bind(this));
    tChild.on('exit', function(d) {
        console.log( this.path +'>>> Exited:'+ d);
        delete ForkDict[tChild.pid]
     }.bind(this));
}

forkit('./DaemonSerial.js');

the error from the console reads as follows:

pi@raspberrypi ~ $ node forktest.js

/home/pi/forktest.js:9
    tChild.stdout.on('data', function(data) {
                  ^
TypeError: Cannot call method 'on' of null
    at forkit (/home/pi/forktest.js:9:19)
    at Object.<anonymous> (/home/pi/forktest.js:19:1)
    at Module._pile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:901:3
Share Improve this question edited May 23, 2017 at 12:32 CommunityBot 11 silver badge asked Mar 8, 2014 at 21:56 CaffeineAddictionCaffeineAddiction 8233 gold badges15 silver badges32 bronze badges 1
  • 2 According to the documentation it doesn't really look async, and I've only ever spawned new processes, but I've never had any issues with this. It does say in the docs that forking could take up to 30ms, and if there's no callback I guess you have to fake one with an interval that checks if it's ready etc. – adeneo Commented Mar 8, 2014 at 22:23
Add a ment  | 

1 Answer 1

Reset to default 9

fork is asynchronous, but its return value is not populated asynchronously. It returns an instance of ChildProcess, that inherits from EventEmitter. An EventEmitter is monly used for asynchronous tasks, but you receive events when something happens instead of using a callback. Like it says in the docs:

These methods follow the mon async programming patterns (accepting a callback or returning an EventEmitter).

In the first example:

  • fork does not have a stdio option. You should probably use silent: true instead; which calls spawn with the stdio option set to "pipe".
  • You try to read from a writable stream (stdin): tChild.stdin.on('data', ... You probably want to use stdout.

It appears that stdin and stdout can be null depending on if you use silent: true or not. See options.silent in the docs for fork:

Boolean If true, stdin, stdout, and stderr of the child will be piped to the parent, otherwise they will be inherited from the parent, see the "pipe" and "inherit" options for spawn()'s stdio for more details (default is false)

So the data is just going to your main script's stdout. You can fix this with (note that your stdio option wasn't doing anything):

tChild = fork( aPath, [], {silent: true});

As I said earlier, you'll need to listen to the data event on stdout.

本文标签: javascriptNodeJS Forked PipeStack Overflow