1'use strict'; 2const common = require('../common'); 3 4if (common.isWindows) 5 common.skip('no signals in Windows'); 6if (!common.isMainThread) 7 common.skip('No signal handling available in Workers'); 8 9const assert = require('assert'); 10const initHooks = require('./init-hooks'); 11const { checkInvocations } = require('./hook-checks'); 12const exec = require('child_process').exec; 13 14const hooks = initHooks(); 15 16hooks.enable(); 17 18// Keep the event loop open so process doesn't exit before receiving signals. 19const interval = setInterval(() => {}, 9999); 20 21process.on('SIGUSR2', common.mustCall(onsigusr2, 2)); 22 23const as = hooks.activitiesOfTypes('SIGNALWRAP'); 24assert.strictEqual(as.length, 1); 25const signal1 = as[0]; 26assert.strictEqual(signal1.type, 'SIGNALWRAP'); 27assert.strictEqual(typeof signal1.uid, 'number'); 28assert.strictEqual(typeof signal1.triggerAsyncId, 'number'); 29checkInvocations(signal1, { init: 1 }, 'when SIGUSR2 handler is set up'); 30 31let count = 0; 32exec(`kill -USR2 ${process.pid}`); 33 34let signal2; 35 36function onsigusr2() { 37 count++; 38 39 if (count === 1) { 40 // first invocation 41 checkInvocations( 42 signal1, { init: 1, before: 1 }, 43 ' signal1: when first SIGUSR2 handler is called for the first time'); 44 45 // Trigger same signal handler again 46 exec(`kill -USR2 ${process.pid}`); 47 } else { 48 // second invocation 49 checkInvocations( 50 signal1, { init: 1, before: 2, after: 1 }, 51 'signal1: when first SIGUSR2 handler is called for the second time'); 52 53 // Install another signal handler 54 process.removeAllListeners('SIGUSR2'); 55 process.on('SIGUSR2', common.mustCall(onsigusr2Again)); 56 57 const as = hooks.activitiesOfTypes('SIGNALWRAP'); 58 // The isTTY checks are needed to allow test to work whether run with 59 // test.py or directly with the node executable. The third signal event 60 // listener is the SIGWINCH handler that node installs when it thinks 61 // process.stdout is a tty. 62 const expectedLen = 2 + (!!process.stdout.isTTY || !!process.stderr.isTTY); 63 assert.strictEqual(as.length, expectedLen); 64 signal2 = as[expectedLen - 1]; // Last item in the array. 65 assert.strictEqual(signal2.type, 'SIGNALWRAP'); 66 assert.strictEqual(typeof signal2.uid, 'number'); 67 assert.strictEqual(typeof signal2.triggerAsyncId, 'number'); 68 69 checkInvocations( 70 signal1, { init: 1, before: 2, after: 1 }, 71 'signal1: when second SIGUSR2 handler is set up'); 72 checkInvocations( 73 signal2, { init: 1 }, 74 'signal2: when second SIGUSR2 handler is setup'); 75 76 exec(`kill -USR2 ${process.pid}`); 77 } 78} 79 80function onsigusr2Again() { 81 clearInterval(interval); 82 setImmediate(() => { 83 checkInvocations( 84 signal1, { init: 1, before: 2, after: 2, destroy: 1 }, 85 'signal1: when second SIGUSR2 handler is called'); 86 checkInvocations( 87 signal2, { init: 1, before: 1 }, 88 'signal2: when second SIGUSR2 handler is called'); 89 }); 90} 91 92process.on('exit', onexit); 93 94function onexit() { 95 hooks.disable(); 96 hooks.sanityCheck('SIGNALWRAP'); 97 checkInvocations( 98 signal1, { init: 1, before: 2, after: 2, destroy: 1 }, 99 'signal1: when second SIGUSR2 process exits'); 100 // Second signal not destroyed yet since its event listener is still active 101 checkInvocations( 102 signal2, { init: 1, before: 1, after: 1 }, 103 'signal2: when second SIGUSR2 process exits'); 104} 105