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'; 23// test-cluster-worker-kill.js 24// verifies that, when a child process is killed (we use SIGKILL) 25// - the parent receives the proper events in the proper order, no duplicates 26// - the exitCode and signalCode are correct in the 'exit' event 27// - the worker.exitedAfterDisconnect flag, and worker.state are correct 28// - the worker process actually goes away 29 30const common = require('../common'); 31const assert = require('assert'); 32const cluster = require('cluster'); 33 34if (cluster.isWorker) { 35 const http = require('http'); 36 const server = http.Server(() => { }); 37 38 server.once('listening', common.mustCall(() => { })); 39 server.listen(0, '127.0.0.1'); 40 41} else if (cluster.isMaster) { 42 43 const KILL_SIGNAL = 'SIGKILL'; 44 const expected_results = { 45 cluster_emitDisconnect: [1, "the cluster did not emit 'disconnect'"], 46 cluster_emitExit: [1, "the cluster did not emit 'exit'"], 47 cluster_exitCode: [null, 'the cluster exited w/ incorrect exitCode'], 48 cluster_signalCode: [KILL_SIGNAL, 49 'the cluster exited w/ incorrect signalCode'], 50 worker_emitDisconnect: [1, "the worker did not emit 'disconnect'"], 51 worker_emitExit: [1, "the worker did not emit 'exit'"], 52 worker_state: ['disconnected', 'the worker state is incorrect'], 53 worker_exitedAfter: [false, 'the .exitedAfterDisconnect flag is incorrect'], 54 worker_died: [true, 'the worker is still running'], 55 worker_exitCode: [null, 'the worker exited w/ incorrect exitCode'], 56 worker_signalCode: [KILL_SIGNAL, 57 'the worker exited w/ incorrect signalCode'] 58 }; 59 const results = { 60 cluster_emitDisconnect: 0, 61 cluster_emitExit: 0, 62 worker_emitDisconnect: 0, 63 worker_emitExit: 0 64 }; 65 66 67 // start worker 68 const worker = cluster.fork(); 69 70 // When the worker is up and running, kill it 71 worker.once('listening', common.mustCall(() => { 72 worker.process.kill(KILL_SIGNAL); 73 })); 74 75 76 // Check cluster events 77 cluster.on('disconnect', common.mustCall(() => { 78 results.cluster_emitDisconnect += 1; 79 })); 80 cluster.on('exit', common.mustCall((worker) => { 81 results.cluster_exitCode = worker.process.exitCode; 82 results.cluster_signalCode = worker.process.signalCode; 83 results.cluster_emitExit += 1; 84 })); 85 86 // Check worker events and properties 87 worker.on('disconnect', common.mustCall(() => { 88 results.worker_emitDisconnect += 1; 89 results.worker_exitedAfter = worker.exitedAfterDisconnect; 90 results.worker_state = worker.state; 91 })); 92 93 // Check that the worker died 94 worker.once('exit', common.mustCall((exitCode, signalCode) => { 95 results.worker_exitCode = exitCode; 96 results.worker_signalCode = signalCode; 97 results.worker_emitExit += 1; 98 results.worker_died = !common.isAlive(worker.process.pid); 99 })); 100 101 process.on('exit', () => { 102 checkResults(expected_results, results); 103 }); 104} 105 106// Some helper functions ... 107 108function checkResults(expected_results, results) { 109 for (const k in expected_results) { 110 const actual = results[k]; 111 const expected = expected_results[k]; 112 113 assert.strictEqual( 114 actual, expected && expected.length ? expected[0] : expected, 115 `${expected[1] || ''} [expected: ${expected[0]} / actual: ${actual}]`); 116 } 117} 118