process.send is conditionally defined in Node.js - node.js

For whatever reason, in Node.js, the function process.send is defined in some environments but not defined in others. For instance, when I fork a child process from a parent process in Node.js like so:
//parent process
var cp = require('child_process');
var k = cp.fork('./child.js',['arg1','arg2','arg3']);
k.send('fail'); //k.send is defined...
process.send("ok, let's try this..."); //process.send is NOT defined
inside the child process:
//child.js
process.send('message'); //process.send is defined, and will send a message to the parent process above
The only way I know how to get around this is:
if (typeof process.send === 'function') {
process.send('what I want to send');
}

Child processes have a process.send method to communicate back with the process that spawned them, while the root process doesn't have any "parent" to communicate, so its not there. From the docs:
In the child the process object will have a send() method, and process will emit objects each time it receives a message on its channel.
To avoid having to "litter the code with conditionals", a temporary solution might be to just put a "noop" function in its place at the top of any "root" files you might be spawning processes from:
process.send = process.send || function () {};

set a condition and call process.send in it
if(process.send){ process.send() }

Workaround for Sapper & Svelte usage:
Basically, this error can be received in flow when you provided SAPPER_EXPORT variable in your environment.
More details about issue: https://github.com/Zimtir/SENT-template/issues/114

Related

How to ensure we listen to a child process' events before they occur?

Here is some node.js code that spawns a linux ls command and prompts its result
const spawn = require('child_process').spawn;
const ls = spawn('ls', ['-l']);
let content = "";
ls.stdout.on('data', function(chunk){
content += chunk.toString();
});
ls.stdout.on('end', function(){
console.log(content);
});
This works well. However, the ls command is launched asynchronously, completely separated from the main nodeJs thread. My concern is that the data and end events on the process' stdout may have occurred before I attached event listeners.
Is there a way to attach event listeners before starting that sub-process ?
Note : I don't think I can wrap a Promise around the spawn function to make this work, as it would rely on events to be properly catched to trigger success/failure (leading back to the problem)
There is no problem here.
Readable streams (since node v0.10) have a (limited) internal buffer that stores data until you read from the stream. If the internal buffer fills up, the backpressure mechanism will kick in, causing the stream to stop reading data from its source.
Once you call .read() or add a data event handler, the internal buffer will start to drain and will then start reading from its source again.

Which events should I use for spawning a child process to ensure I always make a callback

I'm using node to wrap an executable and I'm using the spawn event emitter. See the docs here. There are multiple events to subsribe to.
child = spawn("path/to/exe", args)
child.on('close', exitNormally )
child.on('exit', exitNormally )
child.on('error', exitAbnormally )
child.on('disconnect', exitAbnormally )
Should I be subscribing to all of them or is subscribing to close and error enough? I have a callback that I have to execute regardless of whether the outcome is a success or not. The docs for the events are here but it doesn't seem to say explictly say what I'm asking and I want to confirm that my thinking is correct and I don't miss any exits.
The exit event always will be called if your process ends, so I think it will be enough.

Callback when a child_process has successfully processed a signal

I need to verify that a child_process has successfully been killed because I cannot execute the next action if that process is still alive.
var proc = require('child_process');
var prog = proc.spawn('myprog', ['--option', 'value']);
prog.on('data', function(data) {
// Do something
});
Somewhere else in the code I reach to a certain event and on a certain condition I need to kill prog:
prog.kill('SUGHUP');
// Only when the process has successfully been killed execute next
// Code...
Since kill is probably async, I am using q. I would like to use q on kill but kill does not have a callback which is executed when the signal has successfully been processed.
How to do?
Possible idea
If I send a message to process prog and in process prog when receiving the message I kill it? How can tell a process to self-kill?
Wouldn't prog.exec() with the option killsignal and a callback fit your needs ?

child process not calling close event

I have the following node.js code:
var testProcess = spawn(item.testCommand, [], {
cwd: process.cwd(),
stdio: ['ignore', process.stdout, process.stderr]
});
testProcess.on('close', function(data) {
console.log('test');
});
waitpid(testProcess.pid);
testProcess.kill();
however the close method never gets calls.
The end result I am looking for is that I spwan a process and the the script waits for that child processs to finish (which waitpid() is doing correctly). I want the output/err of the child process to be display to the screen (which the stdio config is doing correctly). I also want to perform code on the close of the child process which I was going to do in the close event (also tried exit), but it does not fire.
Why is the event not not firing?
http://nodejs.org/api/process.html
Note that just because the name of this function is process.kill, it is really just a signal sender, like the kill system call. The signal sent may do something other than kill the target process.
You can specify the signal while Kill() call.
Looking at waitpid() I found out that it returns an object with the exitCode. I changed my code so that I just perform certain actions based on what the value of the exitCode is.

Detect when parent process exits

I will have a parent process that is used to handle webserver restarts. It will signal the child to stop listening for new requests, the child will signal the parent that it has stopped listening, then the parent will signal the new child that it can start listening. In this way, we can accomplish less than 100ms down time for a restart of that level (I have a zero-downtime grandchild restart also, but that is not always enough of a restart).
The service manager will kill the parent when it is time for shutdown. How can the child detect that the parent has ended?
The signals are sent using stdin and stdout of the child process. Perhaps I can detect the end of an stdin stream? I am hoping to avoid a polling interval. Also, I would like this to be a really quick detection if possible.
a simpler solution could be by registering for 'disconnect' in the child process
process.on('disconnect', function() {
console.log('parent exited')
process.exit();
});
This answer is just for providing an example of the node-ffi solution that entropo has proposed (above) (as mentioned it will work on linux):
this is the parent process, it is spawning the child and then exit after 5 seconds:
var spawn = require('child_process').spawn;
var node = spawn('node', [__dirname + '/child.js']);
setTimeout(function(){process.exit(0)}, 5000);
this is the child process (located in child.js)
var FFI = require('node-ffi');
var current = new FFI.Library(null, {"prctl": ["int32", ["int32", "uint32"]]})
//1: PR_SET_PDEATHSIG, 15: SIGTERM
var returned = current.prctl(1,15);
process.on('SIGTERM',function(){
//do something interesting
process.exit(1);
});
doNotExit = function (){
return true;
};
setInterval(doNotExit, 500);
without the current.prctl(1,15) the child will run forever even if the parent is dying. Here it will be signaled with a SIGTERM which will be handled gracefully.
Could you just put an exit listener in the parent process that signals the children?
Edit:
You can also use node-ffi (Node Foreign Function Interface) to call ...
prctl(PR_SET_PDEATHSIG, SIGHUP);
... in Linux. ( man 2 prctl )
I start Node.JS from within a native OSX application as a background worker. To make node.js exit when the parent process which consumes node.js stdout dies/exits, I do the following:
// Watch parent exit when it dies
process.stdout.resume();
process.stdout.on('end', function() {
 process.exit();
});
Easy like that, but I'm not exactly sure if it's what you've been asking for ;-)

Resources