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.org/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._compile (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
fork
is asynchronous, but its return value is not populated asynchronously. It returns an instance of ChildProcess, that inherits from EventEmitter. An EventEmitter is commonly 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 common 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".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 isfalse
)
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With