Skip to content

Commit 450d165

Browse files
committed
lib: add trace-sigint APIs
1 parent 049664b commit 450d165

File tree

7 files changed

+134
-4
lines changed

7 files changed

+134
-4
lines changed

doc/api/util.md

Lines changed: 10 additions & 0 deletions
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

lib/internal/process/pre_execution.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -386,10 +386,7 @@ function setupStacktracePrinterOnSigint() {
386386
if (!getOptionValue('--trace-sigint')) {
387387
return;
388388
}
389-
const { SigintWatchdog } = require('internal/watchdog');
390-
391-
const watchdog = new SigintWatchdog();
392-
watchdog.start();
389+
require('internal/util/trace_sigint').setTraceSigInt(true);
393390
}
394391

395392
function initializeReport() {

lib/internal/util/trace_sigint.js

Lines changed: 29 additions & 0 deletions
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+
};

lib/util.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,3 +491,9 @@ defineLazyProperties(
491491
'internal/util/diff',
492492
['diff'],
493493
);
494+
495+
defineLazyProperties(
496+
module.exports,
497+
'internal/util/trace_sigint',
498+
['setTraceSigInt'],
499+
);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
const { mustCall } = require('../common');
4+
const childProcess = require('child_process');
5+
const util = require('util');
6+
const assert = require('assert');
7+
8+
if (!process.env.CHILD) {
9+
const cp = childProcess.spawn(
10+
process.execPath,
11+
[__filename],
12+
{
13+
env: { ...process.env, CHILD: '1' },
14+
});
15+
let data;
16+
cp.stderr.on('data', (chunk) => {
17+
data = data ? data + chunk : chunk;
18+
});
19+
cp.stderr.on('end', () => {
20+
console.log(data);
21+
assert.strictEqual(/SIGINT/.test(data.toString()), true);
22+
});
23+
cp.on('exit', mustCall((code, signal) => {
24+
assert.strictEqual(signal, 'SIGINT');
25+
assert.strictEqual(code, null);
26+
}));
27+
} else {
28+
util.setTraceSigInt(true);
29+
// Deactivate colors even if the tty does support colors.
30+
process.env.NODE_DISABLE_COLORS = '1';
31+
process.kill(process.pid, 'SIGINT');
32+
while (true);
33+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
3+
const { mustCall } = require('../common');
4+
const childProcess = require('child_process');
5+
const util = require('util');
6+
const assert = require('assert');
7+
8+
if (!process.env.CHILD) {
9+
{
10+
const cp = childProcess.spawn(
11+
process.execPath,
12+
['--trace-sigint', __filename],
13+
{
14+
env: { ...process.env, CHILD: '1' },
15+
});
16+
let data;
17+
cp.stderr.on('data', (chunk) => {
18+
data = data ? data + chunk : chunk;
19+
});
20+
cp.stderr.on('end', () => {
21+
assert.strictEqual(data === undefined, true);
22+
});
23+
cp.on('exit', mustCall((code, signal) => {
24+
assert.strictEqual(signal, 'SIGINT');
25+
assert.strictEqual(code, null);
26+
}));
27+
}
28+
} else {
29+
util.setTraceSigInt(false);
30+
// Deactivate colors even if the tty does support colors.
31+
process.env.NODE_DISABLE_COLORS = '1';
32+
process.kill(process.pid, 'SIGINT');
33+
while (true);
34+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
process.exit(0);
16+
} else {
17+
const w = new Worker(__filename, { workerData: { isWorker: true } });
18+
w.on('exit', common.mustCall((code) => {
19+
assert.strictEqual(code, 0);
20+
}));
21+
}

0 commit comments

Comments
 (0)