Q:

Daemonize 'child_process' that was 'fork'ed

I am trying to achieve a behavior similar to one that httpd has when starting with NodeJS. When we say:
service httpd start

In ps, we'll see:
[root@dev ~]# service httpd start
Starting httpd:                                            [  OK  ]
[root@dev ~]# ps auxf | grep httpd
root      3395  0.0  0.1   6336   304 pts/0    R+   12:03   0:00  |       \_ grep httpd
root      3391  0.0  1.3 175216  3656 ?        Ss   12:02   0:00 /usr/sbin/httpd
apache    3393  0.0  0.9 175216  2432 ?        S    12:02   0:00  \_ /usr/sbin/httpd

Notice how httpd master and child have no terminal (? is shown instead of pts/0 for grep).
Now... I need an IPC channel and therefore I use child_process.fork but no matter what I do, every time I see a terminal still attached to my daemon. Here is the code you are welcome to experiment on:
c.js - controller
var cp = require('child_process');

var d = cp.fork('d.js', {});

d.on('message', function() {
  d.disconnect();
  d.unref();
});

d.js - daemon
process.send('ready');

setTimeout(function() {
  console.log('test');
}, 10000);

And this is what I see in terminal:
[root@dev ~]# node c.js                 # running the control script
[root@dev ~]# ps auxf | grep node       # my terminal is interactive again so I check
root      3472  0.0  0.3 103308   864 pts/0    S+   12:13   0:00  |       \_ grep node
root      3466  1.1  5.6 648548 14904 pts/0    Sl   12:13   0:00 /usr/bin/node d.js
[root@dev ~]# test                      # appears outta nowhere because d.js still has this stdout

d.js still has my pts/0 and writes test to it even when it's already interactive with bash for me.
How do I fix that and make daemon drop the terminal? I don't care which side (c.js or d.js) gets adjustments to code, I control both, but I need that IPC channel and therefore this has to be done via fork.

A:

This can be solved by ditching fork in favor of spawn. Same code can then be rewritten to:
var cp = require('child_process');
var d = cp.spawn(process.execPath, ['./d.js'], {
  detached: true,
  stdio: ['ignore', 'ignore', 'ignore', 'ipc']
});

d.unref();
d.disconnect();

The stdio part is how fork works internally. I have no idea why they decided to not expose the full array and instead gave only silent.
d.js will then have no terminal right at the start (it will be /dev/null - same as httpd). Not tested on Windows.

