Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

child_process: support AbortSignal in fork #36603

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 9 additions & 2 deletions doc/api/child_process.md
Expand Up @@ -351,6 +351,9 @@ controller.abort();
<!-- YAML
added: v0.5.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/36603
description: AbortSignal support was added.
- version:
- v13.2.0
- v12.16.0
Expand All @@ -375,9 +378,11 @@ changes:
* `execPath` {string} Executable used to create the child process.
* `execArgv` {string[]} List of string arguments passed to the executable.
**Default:** `process.execArgv`.
* `gid` {number} Sets the group identity of the process (see setgid(2)).
* `serialization` {string} Specify the kind of serialization used for sending
messages between processes. Possible values are `'json'` and `'advanced'`.
See [Advanced serialization][] for more details. **Default:** `'json'`.
* `signal` {AbortSignal} Allows closing the subprocess using an AbortSignal.
* `silent` {boolean} If `true`, stdin, stdout, and stderr of the child will be
piped to the parent, otherwise they will be inherited from the parent, see
the `'pipe'` and `'inherit'` options for [`child_process.spawn()`][]'s
Expand All @@ -386,10 +391,9 @@ changes:
When this option is provided, it overrides `silent`. If the array variant
is used, it must contain exactly one item with value `'ipc'` or an error
will be thrown. For instance `[0, 1, 2, 'ipc']`.
* `uid` {number} Sets the user identity of the process (see setuid(2)).
* `windowsVerbatimArguments` {boolean} No quoting or escaping of arguments is
done on Windows. Ignored on Unix. **Default:** `false`.
* `uid` {number} Sets the user identity of the process (see setuid(2)).
* `gid` {number} Sets the group identity of the process (see setgid(2)).
* Returns: {ChildProcess}

The `child_process.fork()` method is a special case of
Expand Down Expand Up @@ -420,6 +424,9 @@ current process.
The `shell` option available in [`child_process.spawn()`][] is not supported by
`child_process.fork()` and will be ignored if set.

The `signal` option works exactly the same way it does in
[`child_process.spawn()`][].

### `child_process.spawn(command[, args][, options])`
<!-- YAML
added: v0.1.90
Expand Down
4 changes: 2 additions & 2 deletions lib/child_process.js
Expand Up @@ -140,7 +140,7 @@ function fork(modulePath /* , args, options */) {
options.execPath = options.execPath || process.execPath;
options.shell = false;

return spawn(options.execPath, args, options);
return spawnWithSignal(options.execPath, args, options);
}

function _forkChild(fd, serializationMode) {
Expand Down Expand Up @@ -758,7 +758,7 @@ function spawnWithSignal(file, args, options) {
validateAbortSignal(options.signal, 'options.signal');
function kill() {
if (child._handle) {
child._handle.kill('SIGTERM');
child.kill('SIGTERM');
child.emit('error', new AbortError());
}
}
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/child-process-stay-alive-forever.js
@@ -0,0 +1,3 @@
setInterval(() => {
// Starting an interval to stay alive.
}, 1000);
33 changes: 33 additions & 0 deletions test/parallel/test-child-process-fork-abort-signal.js
@@ -0,0 +1,33 @@
'use strict';

const { mustCall } = require('../common');
const { strictEqual } = require('assert');
const fixtures = require('../common/fixtures');
const { fork } = require('child_process');

{
// Test aborting a forked child_process after calling fork
const ac = new AbortController();
const { signal } = ac;
const cp = fork(fixtures.path('child-process-stay-alive-forever.js'), {
signal
});
cp.on('exit', mustCall());
cp.on('error', mustCall((err) => {
strictEqual(err.name, 'AbortError');
}));
process.nextTick(() => ac.abort());
}
{
// Test passing an already aborted signal to a forked child_process
const ac = new AbortController();
const { signal } = ac;
ac.abort();
const cp = fork(fixtures.path('child-process-stay-alive-forever.js'), {
signal
});
cp.on('exit', mustCall());
cp.on('error', mustCall((err) => {
strictEqual(err.name, 'AbortError');
}));
}