9

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.

tshepang
  • 12,111
  • 21
  • 91
  • 136
700 Software
  • 85,281
  • 83
  • 234
  • 341

4 Answers4

17

a simpler solution could be by registering for 'disconnect' in the child process

process.on('disconnect', function() {
  console.log('parent exited')
  process.exit();
});
regata
  • 311
  • 2
  • 6
  • Thank you! I tried everything and this seems to be the only way to catch that your parent process was killed -9. – Abdullah Jibaly May 17 '14 at 21:26
  • I totally agree that this is great solution. In my case I'm listening on SIGTERM event from parent process and also (if anything bad happens and I need to restart the parent process) on disconnect event. In my case the problem is noticeable, because child process creates server holding port, so starting again cause "ERRADDRINUSE". This solves the problem :) – JakubKnejzlik Dec 23 '14 at 02:39
8

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.

hellvinz
  • 3,460
  • 20
  • 16
  • For those implementing this solution. Do not call process.exit(1) until you are actually done. logger.warn("SIGTERM. Exiting gracefully.", function() {process.exit(1);}) – itaifrenkel Jul 16 '14 at 09:45
  • It looks like node-ffi has been deprecated in favor of newer module "ffi". – mpr Jul 24 '18 at 16:22
5

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 )

Community
  • 1
  • 1
entropo
  • 2,481
  • 15
  • 15
  • I think this will work. The parent is killed when it is time to shut down, but I am pretty sure that the exit listener will still work. Perhaps I can still [check for a parent process id every few seconds](http://stackoverflow.com/questions/5566009/node-js-parent-process-id) and if it becomes the number 1, that means the parent has died. – 700 Software Apr 06 '11 at 12:03
  • 3
    If you're shutting down, your processes will receive `SIGTERM` first. You can capture this and do cleanup in this way too: `process.on('SIGTERM', function () { console.log('Got SIGTERM, exiting...'); // do some cleanup here... process.exit(0); });` – entropo Apr 06 '11 at 17:07
  • 1
    And yes, having children periodically check if their `PPID` became `1` is a good fallback for cases where the parent didn't exit cleanly. See also: http://stackoverflow.com/questions/269494/how-can-i-cause-a-child-process-to-exit-when-the-parent-does – entropo Apr 06 '11 at 17:25
2

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 ;-)

Sascha Reuter
  • 355
  • 2
  • 7