1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23const common = require('../common'); 24const assert = require('assert'); 25const cluster = require('cluster'); 26 27if (cluster.isWorker) { 28 const http = require('http'); 29 http.Server(() => { 30 31 }).listen(0, '127.0.0.1'); 32 33 cluster.worker.on('disconnect', common.mustCall(() => { 34 process.exit(42); 35 })); 36 37} else if (cluster.isMaster) { 38 39 const checks = { 40 cluster: { 41 emitDisconnect: false, 42 emitExit: false, 43 callback: false 44 }, 45 worker: { 46 emitDisconnect: false, 47 emitDisconnectInsideWorker: false, 48 emitExit: false, 49 state: false, 50 voluntaryMode: false, 51 died: false 52 } 53 }; 54 55 // start worker 56 const worker = cluster.fork(); 57 58 // Disconnect worker when it is ready 59 worker.once('listening', common.mustCall(() => { 60 const w = worker.disconnect(); 61 assert.strictEqual(worker, w, `${worker.id} did not return a reference`); 62 })); 63 64 // Check cluster events 65 cluster.once('disconnect', common.mustCall(() => { 66 checks.cluster.emitDisconnect = true; 67 })); 68 cluster.once('exit', common.mustCall(() => { 69 checks.cluster.emitExit = true; 70 })); 71 72 // Check worker events and properties 73 worker.once('disconnect', common.mustCall(() => { 74 checks.worker.emitDisconnect = true; 75 checks.worker.voluntaryMode = worker.exitedAfterDisconnect; 76 checks.worker.state = worker.state; 77 })); 78 79 // Check that the worker died 80 worker.once('exit', common.mustCall((code) => { 81 checks.worker.emitExit = true; 82 checks.worker.died = !common.isAlive(worker.process.pid); 83 checks.worker.emitDisconnectInsideWorker = code === 42; 84 })); 85 86 process.once('exit', () => { 87 88 const w = checks.worker; 89 const c = checks.cluster; 90 91 // events 92 assert.ok(w.emitDisconnect, 'Disconnect event did not emit'); 93 assert.ok(w.emitDisconnectInsideWorker, 94 'Disconnect event did not emit inside worker'); 95 assert.ok(c.emitDisconnect, 'Disconnect event did not emit'); 96 assert.ok(w.emitExit, 'Exit event did not emit'); 97 assert.ok(c.emitExit, 'Exit event did not emit'); 98 99 // flags 100 assert.strictEqual(w.state, 'disconnected'); 101 assert.strictEqual(w.voluntaryMode, true); 102 103 // is process alive 104 assert.ok(w.died, 'The worker did not die'); 105 }); 106} 107