In the process of multi-process programming, it is necessary to deal with the relationship between parent and child processes, otherwise orphan process and zombie process are easy to appear, resulting in unexpected consequences.

Orphan/Zombie processes

  • Orphan process – When the parent exits before the child, the child is taken over by the system process
  • Zombie process – When the child exits, the parent process does not process the child exit message

Simulated Orphan process

const cp = require('child_process'); if (! Process.send) {// Main process const child = cp.fork(__filename); child.disconnect(); // Close ipc channel child.unref(); Log (' bye my son ${child-.pid}, I'm daddy ${process.pid} '); SetInterval (() => {console.log(' OMG, I'm alive, where is my daddy ${process.ppid} ')}, 2000)} else {// child process setInterval(() => {console.log(' OMG, I'm alive, where is my daddy ${process.ppid} ')}, 2000)}Copy the code

Result: Parent exits, child remains

$node test.js bye my son 665666, I'm daddy 665659 $OMG, I'm alive, where is my daddy 1678 OMG, I'm alive, OMG, I'm alive, where is my daddy 1678Copy the code

Child process takeover: The child process is taken over by systMD

$ ps -L 1678
PID     LWP TTY      STAT   TIME COMMAND
1678    1678 ?        Ss     0:04 /lib/systemd/systemd --user
Copy the code

Simulated zombie process

const cp = require('child_process'); if (! process.send) { const child = cp.fork(__filename); Console. log(' Sorry my son ${child.pid}, I'm daddy ${process.pid}, I'm too busy Too look after you '); while(true) {}; } else {console.log(' daddy!!! ????? i'm ${process.pid} hungry to die`); }Copy the code

Result: The child process exits, and the parent process is not processed in time

$ node test.js 
sorry my son 669073, i'm daddy 669066, i'm too busy too look after you
daddy !!!??? i'm 669073 hungry to die
Copy the code

Child process converts to Zombie: Zombie

$ ps -L 669073
PID     LWP TTY      STAT   TIME COMMAND
669073  669073 pts/3    Z+     0:00 [node] <defunct>
Copy the code

Q&A

IPC channel closed

Connected === false or process.channel === undefined, An error will be thrown if communication continues through IPC.

safeSend

function safeSend(args) {
  process.channel && process.send(args)
}
Copy the code

Note: Disconnet only closes IPC, not child processes

Graceful exit

Do not use the forced exit signal SIGINT, otherwise orphan processes will be created. SIGTERM is recommended because SIGTERM can be blocked to allow time to clean up before exiting.

clean up

Process.on ('SIGTERM', () => cleanup()) process.on('SIGINT', () => {console.warn('suggest not to use CTRL+C,  this operation will produce orphan process'); cleanup(); }) function cleanup() { child.kill(); // The SIGTERM signal process.exit(0) is used by default; }Copy the code

Sub-process cluster management

Refer to the Cluster module

conclusion

Although I know the Cluster module of Node, I did not consider this core module because of my preconceived understanding that the Cluster module is usually used in load balancing scenarios. At that time, I was still considering writing a module of my own 🤣. Today I read the source code of Cluster, I can only say 👍 bend four(wonderful). Cluster is not a substitute for fork and is recommended when clustering is possible. Refer to it in scenarios where you can only use fork.

Follow my wechat official account “SUNTOPO WLOG”, welcome to leave a comment and discuss, I will reply as much as possible, thank you for reading.