11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ciif (common.isWindows)
51cb0ef41Sopenharmony_ci  common.skip('no signals in Windows');
61cb0ef41Sopenharmony_ciif (!common.isMainThread)
71cb0ef41Sopenharmony_ci  common.skip('No signal handling available in Workers');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciconst assert = require('assert');
101cb0ef41Sopenharmony_ciconst initHooks = require('./init-hooks');
111cb0ef41Sopenharmony_ciconst { checkInvocations } = require('./hook-checks');
121cb0ef41Sopenharmony_ciconst exec = require('child_process').exec;
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciconst hooks = initHooks();
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cihooks.enable();
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci// Keep the event loop open so process doesn't exit before receiving signals.
191cb0ef41Sopenharmony_ciconst interval = setInterval(() => {}, 9999);
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciprocess.on('SIGUSR2', common.mustCall(onsigusr2, 2));
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ciconst as = hooks.activitiesOfTypes('SIGNALWRAP');
241cb0ef41Sopenharmony_ciassert.strictEqual(as.length, 1);
251cb0ef41Sopenharmony_ciconst signal1 = as[0];
261cb0ef41Sopenharmony_ciassert.strictEqual(signal1.type, 'SIGNALWRAP');
271cb0ef41Sopenharmony_ciassert.strictEqual(typeof signal1.uid, 'number');
281cb0ef41Sopenharmony_ciassert.strictEqual(typeof signal1.triggerAsyncId, 'number');
291cb0ef41Sopenharmony_cicheckInvocations(signal1, { init: 1 }, 'when SIGUSR2 handler is set up');
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cilet count = 0;
321cb0ef41Sopenharmony_ciexec(`kill -USR2 ${process.pid}`);
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_cilet signal2;
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_cifunction onsigusr2() {
371cb0ef41Sopenharmony_ci  count++;
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  if (count === 1) {
401cb0ef41Sopenharmony_ci    // first invocation
411cb0ef41Sopenharmony_ci    checkInvocations(
421cb0ef41Sopenharmony_ci      signal1, { init: 1, before: 1 },
431cb0ef41Sopenharmony_ci      ' signal1: when first SIGUSR2 handler is called for the first time');
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci    // Trigger same signal handler again
461cb0ef41Sopenharmony_ci    exec(`kill -USR2 ${process.pid}`);
471cb0ef41Sopenharmony_ci  } else {
481cb0ef41Sopenharmony_ci    // second invocation
491cb0ef41Sopenharmony_ci    checkInvocations(
501cb0ef41Sopenharmony_ci      signal1, { init: 1, before: 2, after: 1 },
511cb0ef41Sopenharmony_ci      'signal1: when first SIGUSR2 handler is called for the second time');
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci    // Install another signal handler
541cb0ef41Sopenharmony_ci    process.removeAllListeners('SIGUSR2');
551cb0ef41Sopenharmony_ci    process.on('SIGUSR2', common.mustCall(onsigusr2Again));
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci    const as = hooks.activitiesOfTypes('SIGNALWRAP');
581cb0ef41Sopenharmony_ci    // The isTTY checks are needed to allow test to work whether run with
591cb0ef41Sopenharmony_ci    // test.py or directly with the node executable. The third signal event
601cb0ef41Sopenharmony_ci    // listener is the SIGWINCH handler that node installs when it thinks
611cb0ef41Sopenharmony_ci    // process.stdout is a tty.
621cb0ef41Sopenharmony_ci    const expectedLen = 2 + (!!process.stdout.isTTY || !!process.stderr.isTTY);
631cb0ef41Sopenharmony_ci    assert.strictEqual(as.length, expectedLen);
641cb0ef41Sopenharmony_ci    signal2 = as[expectedLen - 1]; // Last item in the array.
651cb0ef41Sopenharmony_ci    assert.strictEqual(signal2.type, 'SIGNALWRAP');
661cb0ef41Sopenharmony_ci    assert.strictEqual(typeof signal2.uid, 'number');
671cb0ef41Sopenharmony_ci    assert.strictEqual(typeof signal2.triggerAsyncId, 'number');
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci    checkInvocations(
701cb0ef41Sopenharmony_ci      signal1, { init: 1, before: 2, after: 1 },
711cb0ef41Sopenharmony_ci      'signal1: when second SIGUSR2 handler is set up');
721cb0ef41Sopenharmony_ci    checkInvocations(
731cb0ef41Sopenharmony_ci      signal2, { init: 1 },
741cb0ef41Sopenharmony_ci      'signal2: when second SIGUSR2 handler is setup');
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci    exec(`kill -USR2 ${process.pid}`);
771cb0ef41Sopenharmony_ci  }
781cb0ef41Sopenharmony_ci}
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_cifunction onsigusr2Again() {
811cb0ef41Sopenharmony_ci  clearInterval(interval);
821cb0ef41Sopenharmony_ci  setImmediate(() => {
831cb0ef41Sopenharmony_ci    checkInvocations(
841cb0ef41Sopenharmony_ci      signal1, { init: 1, before: 2, after: 2, destroy: 1 },
851cb0ef41Sopenharmony_ci      'signal1: when second SIGUSR2 handler is called');
861cb0ef41Sopenharmony_ci    checkInvocations(
871cb0ef41Sopenharmony_ci      signal2, { init: 1, before: 1 },
881cb0ef41Sopenharmony_ci      'signal2: when second SIGUSR2 handler is called');
891cb0ef41Sopenharmony_ci  });
901cb0ef41Sopenharmony_ci}
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ciprocess.on('exit', onexit);
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_cifunction onexit() {
951cb0ef41Sopenharmony_ci  hooks.disable();
961cb0ef41Sopenharmony_ci  hooks.sanityCheck('SIGNALWRAP');
971cb0ef41Sopenharmony_ci  checkInvocations(
981cb0ef41Sopenharmony_ci    signal1, { init: 1, before: 2, after: 2, destroy: 1 },
991cb0ef41Sopenharmony_ci    'signal1: when second SIGUSR2 process exits');
1001cb0ef41Sopenharmony_ci  // Second signal not destroyed yet since its event listener is still active
1011cb0ef41Sopenharmony_ci  checkInvocations(
1021cb0ef41Sopenharmony_ci    signal2, { init: 1, before: 1, after: 1 },
1031cb0ef41Sopenharmony_ci    'signal2: when second SIGUSR2 process exits');
1041cb0ef41Sopenharmony_ci}
105