I am currently trying to find a way to end all worker threads spawned from some master thread after any of them finishes. I've looked at various schemes for communication between worker threads (e.g. cluster.worker.send()
, process.send()
, etc.), but none of them seem to work.
The code that I have so far is quite simple:
const cluster = require('cluster')
const os = require('os')
if ( cluster.isMaster ) {
let children = []
for ( let i = 0; i < os.cpus().length; i++ ) {
children.push(cluster.fork())
}
process.on('message', (msg) => {
if ( msg.cmd === 'shutdown' ) {
console.log('shutting down')
children.forEach(child => {
child.kill()
})
}
})
} else {
console.log('I am worker #' + cluster.worker.id)
let time = Date.now()
while ( Date.now() < time + cluster.worker.id * 1000 ) {
// do nothing for some time
}
console.log('I am worker #' + cluster.worker.id + ' and I am done')
process.send({cmd: 'shutdown'})
}
The first part creates a child process for each CPU using the cluster
module. Next, the master process expects some kind of shutdown message from any of the workers. Each worker runs some process, and, after a certain amount of time, sends a shutdown message to the main thread. At this point, the master thread should trigger all the other threads to shut down, but instead the message is never received. This seems to be the problem but I haven't been able to find a way to get this message sent.
When the code runs, each process sends an 'I am done' message but the threads are not killed.
There are a couple of things you need to change:
cluster.on
instead of process.on
, as process.on
is for the child process, not the parent process.child.process.kill()
instead of child.kill()
.const cluster = require('cluster')
const os = require('os')
if ( cluster.isMaster ) {
let children = []
for ( let i = 0; i < os.cpus().length; i++ ) {
children.push(cluster.fork())
}
cluster.on('message', (worker, msg) => {
if (msg.command = 'shutdown') {
// Kill every cluster worker
children.forEach(child => {
child.process.kill()
})
}
})
} else {
console.log('I am worker #' + cluster.worker.id)
let time = Date.now()
while ( Date.now() < time + cluster.worker.id * 1000 ) {
// do nothing for some time
}
console.log('I am worker #' + cluster.worker.id + ' and I am done')
process.send({command: 'shutdown'})
}