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.