◐ Shell
clean mode source ↗

lib: add trace-sigint APIs · nodejs/node@e055539

Original file line numberDiff line numberDiff line change

@@ -739,6 +739,16 @@ fs.access('file/that/does/not/exist', (err) => {

739739

});

740740

```

741741
742+

## `util.setTraceSigInt(enable)`

743+
744+

<!-- YAML

745+

added: REPLACEME

746+

-->

747+
748+

* `enable` {boolean}

749+
750+

Enable or disable printing a stack trace on `SIGINT`. The API is only available on the main thread.

751+
742752

## `util.inherits(constructor, superConstructor)`

743753
744754

<!-- YAML

Original file line numberDiff line numberDiff line change

@@ -393,10 +393,7 @@ function setupStacktracePrinterOnSigint() {

393393

if (!getOptionValue('--trace-sigint')) {

394394

return;

395395

}

396-

const { SigintWatchdog } = require('internal/watchdog');

397-
398-

const watchdog = new SigintWatchdog();

399-

watchdog.start();

396+

require('internal/util/trace_sigint').setTraceSigInt(true);

400397

}

401398
402399

function initializeReport() {

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,29 @@

1+

'use strict';

2+
3+

const { isMainThread } = require('worker_threads');

4+

const {

5+

ERR_WORKER_UNSUPPORTED_OPERATION,

6+

} = require('internal/errors').codes;

7+
8+

let sigintWatchdog;

9+

function getSigintWatchdog() {

10+

if (!sigintWatchdog) {

11+

const { SigintWatchdog } = require('internal/watchdog');

12+

sigintWatchdog = new SigintWatchdog();

13+

}

14+

return sigintWatchdog;

15+

}

16+
17+

function setTraceSigInt(enable) {

18+

if (!isMainThread)

19+

throw new ERR_WORKER_UNSUPPORTED_OPERATION('Calling util.setTraceSigInt');

20+

if (enable) {

21+

getSigintWatchdog().start();

22+

} else {

23+

getSigintWatchdog().stop();

24+

}

25+

};

26+
27+

module.exports = {

28+

setTraceSigInt,

29+

};

Original file line numberDiff line numberDiff line change

@@ -535,3 +535,9 @@ defineLazyProperties(

535535

'internal/util/diff',

536536

['diff'],

537537

);

538+
539+

defineLazyProperties(

540+

module.exports,

541+

'internal/util/trace_sigint',

542+

['setTraceSigInt'],

543+

);

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,20 @@

1+

'use strict';

2+
3+

const common = require('../common');

4+
5+

const assert = require('assert');

6+

const util = require('util');

7+

const { Worker, workerData } = require('worker_threads');

8+
9+

if (workerData?.isWorker) {

10+

assert.throws(() => {

11+

util.setTraceSigInt(true);

12+

}, {

13+

code: 'ERR_WORKER_UNSUPPORTED_OPERATION',

14+

});

15+

} else {

16+

const w = new Worker(__filename, { workerData: { isWorker: true } });

17+

w.on('exit', common.mustCall((code) => {

18+

assert.strictEqual(code, 0);

19+

}));

20+

}

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,32 @@

1+

'use strict';

2+
3+

const { mustCall } = require('../common');

4+

const childProcess = require('child_process');

5+

const assert = require('assert');

6+

const util = require('util');

7+
8+

if (process.env.CHILD === 'true') {

9+

main();

10+

} else {

11+

// Use inherited stdio child process to prevent test tools from determining

12+

// the case as crashed from SIGINT

13+

const cp = childProcess.spawn(

14+

process.execPath,

15+

[__filename],

16+

{

17+

env: { ...process.env, CHILD: 'true' },

18+

stdio: 'inherit',

19+

});

20+

cp.on('exit', mustCall((code, signal) => {

21+

assert.strictEqual(signal, 'SIGINT');

22+

assert.strictEqual(code, null);

23+

}));

24+

}

25+
26+

function main() {

27+

util.setTraceSigInt(true);

28+

// Deactivate colors even if the tty does support colors.

29+

process.env.NODE_DISABLE_COLORS = '1';

30+

process.kill(process.pid, 'SIGINT');

31+

while (true);

32+

}

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,11 @@

1+

KEYBOARD_INTERRUPT: Script execution was interrupted by `SIGINT`

2+

at main (*/test-start-trace-sigint.js:*)

3+

at */test-start-trace-sigint.js:*

4+

at *

5+

at *

6+

at *

7+

at *

8+

at *

9+

at *

10+

at *

11+

at *

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,32 @@

1+

'use strict';

2+
3+

const { mustCall } = require('../common');

4+

const childProcess = require('child_process');

5+

const assert = require('assert');

6+

const util = require('util');

7+
8+

if (process.env.CHILD === 'true') {

9+

main();

10+

} else {

11+

// Use inherited stdio child process to prevent test tools from determining

12+

// the case as crashed from SIGINT

13+

const cp = childProcess.spawn(

14+

process.execPath,

15+

['--trace-sigint', __filename],

16+

{

17+

env: { ...process.env, CHILD: 'true' },

18+

stdio: 'inherit',

19+

});

20+

cp.on('exit', mustCall((code, signal) => {

21+

assert.strictEqual(signal, 'SIGINT');

22+

assert.strictEqual(code, null);

23+

}));

24+

}

25+
26+

function main() {

27+

util.setTraceSigInt(false);

28+

// Deactivate colors even if the tty does support colors.

29+

process.env.NODE_DISABLE_COLORS = '1';

30+

process.kill(process.pid, 'SIGINT');

31+

while (true);

32+

}