-
Notifications
You must be signed in to change notification settings - Fork 30.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cluster: fix race condition setting suicide prop
There is no guarantee that the `suicide` property of a worker in the master process is going to be set when the `disconnect` and `exit` events are emitted. To fix it, wait for the ACK of the suicide message from the master before disconnecting the worker. Also, there's no need to send the suicide message from the worker if the disconnection has been initiated in the master. Add `test-cluster-disconnect-suicide-race` that forks a lot of workers to consistently reproduce the issue this patch tries to solve. Modify `test-regress-GH-3238` so it checks both the `kill` and `disconnect` cases. Also take into account that the `disconnect` event may be received after the `exit` event. PR-URL: #4349 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
- Loading branch information
1 parent
265e2f5
commit 9571be1
Showing
3 changed files
with
75 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
const assert = require('assert'); | ||
const cluster = require('cluster'); | ||
const os = require('os'); | ||
|
||
if (cluster.isMaster) { | ||
function forkWorker(action) { | ||
const worker = cluster.fork({ action }); | ||
worker.on('disconnect', common.mustCall(() => { | ||
assert.strictEqual(worker.suicide, true); | ||
})); | ||
|
||
worker.on('exit', common.mustCall(() => { | ||
assert.strictEqual(worker.suicide, true); | ||
})); | ||
} | ||
|
||
const cpus = os.cpus().length; | ||
const tries = cpus > 8 ? 64 : cpus * 8; | ||
|
||
cluster.on('exit', common.mustCall((worker, code) => { | ||
assert.strictEqual(code, 0, 'worker exited with error'); | ||
}, tries * 2)); | ||
|
||
for (let i = 0; i < tries; ++i) { | ||
forkWorker('disconnect'); | ||
forkWorker('kill'); | ||
} | ||
} else { | ||
cluster.worker[process.env.action](); | ||
} |