-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
Closed
Description
Version
v18.16.0 (haven't check older version btw)
Platform
Linux 6.5.0-21-generic #21-Ubuntu SMP PREEMPT_DYNAMIC Wed Feb 7 14:17:40 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
Subsystem
No response
What steps will reproduce the bug?
- Run the below code block using
node index.jse.g.
const http = require("node:http");
const process = require("node:process");
if (cluster.isPrimary) {
// Keep track of http requests
let numReqs = 0;
let inter = setInterval(() => {
console.log(`numReqs = ${numReqs}`);
}, 1000);
// Count requests
function messageHandler(msg) {
if (msg.cmd && msg.cmd === "notifyRequest") {
numReqs += 1;
}
}
// Start workers and listen for messages containing notifyRequest
const numCPUs = require("node:os").availableParallelism();
for (let i = 0; i < 2; i++) {
cluster.fork();
}
for (const id in cluster.workers) {
cluster.workers[id].on("message", messageHandler);
}
cluster.on("exit", (worker, code, signal) => {
console.log(
`--------------EAD---------------${worker.exitedAfterDisconnect}-----`,
);
if (worker.exitedAfterDisconnect === true) {
console.log("Oh, it was just voluntary – no need to worry");
} else {
console.log(`-----------EXIT------------------${worker.process.pid}`);
}
});
process.on("SIGINT", async (signal) => {
console.log("----------------SIGINT----------------------");
await killChildProcesses(cluster);
console.log("-----------------DONE------------------");
process.exit(0);
});
} else {
// Worker processes have a http server.
const server = http
.Server((req, res) => {
res.writeHead(200);
res.end("hello world\n");
// Notify primary about the request
process.send({ cmd: "notifyRequest" });
})
.listen(4000);
process.on("SIGTERM", (signal) => {
console.log("----------------SIGTERM----------------------");
server.close(() => {
console.log("----------------------CLOSED---------------------");
process.exit(0);
});
});
}
function killChildProcesses(cluster) {
return new Promise((resolve) => {
const aliveWorkers = Object.values(cluster.workers || {}).filter(
(worker) => {
return worker && !worker.isDead();
},
);
if (aliveWorkers.length === 0) {
resolve();
return;
}
let workersAlive = aliveWorkers.length;
const handleWorkerExit = () => {
workersAlive--;
if (workersAlive === 0) {
resolve();
}
};
aliveWorkers.forEach((worker) => {
console.log("-----------KILLING-----------");
worker.on("exit", handleWorkerExit);
worker.kill();
});
});
}
- find out the primary process number for this e.g.
ps -ef | grep index.js - kill the process with
SIGINTsignal, i.e.kill -SIGINT <pid> - the resulting console output is as below
----------------SIGINT----------------------
-----------KILLING-----------
-----------KILLING-----------
----------------SIGTERM----------------------
----------------SIGTERM----------------------
----------------------CLOSED---------------------
----------------------CLOSED---------------------
--------------EAD---------------false--0---
-----------EXIT------------------<worker-1-pid>
--------------EAD---------------false--0---
-----------EXIT------------------<worker-2-pid>
-----------------DONE------------------
How often does it reproduce? Is there a required condition?
always
What is the expected behavior? Why is that the expected behavior?
The expected behavior should be
----------------SIGINT----------------------
-----------KILLING-----------
-----------KILLING-----------
----------------SIGTERM----------------------
----------------SIGTERM----------------------
----------------------CLOSED---------------------
----------------------CLOSED---------------------
--------------EAD---------------false--0---
Oh, it was just voluntary – no need to worry
--------------EAD---------------false--0---
Oh, it was just voluntary – no need to worry
-----------------DONE------------------
What do you see instead?
As you can see the worker.exitedAfterDisconnect is not true, but the documentation (https://nodejs.org/api/cluster.html#workerexitedafterdisconnect) states that it should be true if you kill() or disconnect() the worker.
As you can the worker process exited with code 0, I don't understand which other way it can be exited with code 0 other that what the code is doing...
Additional information
No response
Metadata
Metadata
Assignees
Labels
No labels
