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

v15.13.0 proposal #37977

Merged
merged 85 commits into from
Mar 31, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
01dcf4d
tools: update ESLint to 7.22.0
cjihrig Mar 12, 2021
836cb67
src: add .note.GNU-stack section
jayaddison Mar 9, 2021
4487483
test: fix test-fs-utimes on non-Y2K38 file systems
Trott Mar 11, 2021
a8edf1a
test: add known_issues test for #13683
Trott Mar 13, 2021
2e82a97
doc: add gyp maintain info
gengjiawen Mar 16, 2021
dc9cd43
buffer: implement btoa and atob
jasnell Mar 17, 2021
505f9c9
test: app atob web platform tests
jasnell Mar 17, 2021
bfe3f21
crypto: fix crypto.verify callback invocation with a private keyobject
panva Mar 18, 2021
d1a3e0e
node-api: stop ref gc during environment teardown
gabrielschulhof Mar 4, 2021
95aa032
child_process: add timeout to spawn and fork
Feb 6, 2021
6ed9e0b
test: improve test-arm-math-illegal-instruction
marsonya Mar 15, 2021
50f3ad1
doc: fix typo in stream docs
isker Mar 11, 2021
c4183bb
doc: fix AbortError example for timers
dbachko Mar 13, 2021
3a440ec
lib: fix typo in lib/internal/crypto/certificate.js
marsonya Mar 13, 2021
6e2b609
lib: fix typo in internal/modules/esm/module_job.js
marsonya Mar 16, 2021
2227aa6
tools: partially detect quic support in shared_openssl
jasnell Mar 9, 2021
9e6aa19
deps: add ngtcp2 and nghttp3
jasnell Mar 9, 2021
4700042
doc: add @linkgoron to collaborators
Linkgoron Mar 19, 2021
af7489c
lib: add brand checks to AbortController and AbortSignal
MattiasBuelens Mar 11, 2021
c37806d
crypto: use macro map for NodeCryptoError
RaisinTen Mar 14, 2021
9d160da
doc: add legacy status to stability index
jasnell Mar 17, 2021
185d4cd
doc: revoke deprecation of legacy url, change status to legacy
jasnell Mar 17, 2021
6da0a0e
doc: apply style for legacy status
jasnell Mar 19, 2021
b09d032
doc: move Derek Lewis back to collaborators
DerekNonGeneric Mar 12, 2021
b6be472
tools: update gitignore for CMake
gengjiawen Mar 18, 2021
3376051
doc: fix JS flavor selection
aduh95 Mar 17, 2021
e85f311
test: refactor code to use AbortSignal.abort()
manekinekko Mar 18, 2021
a520581
http: add http.ClientRequest.getRawHeaderNames()
simov Mar 8, 2021
9f61cbd
test: account for OOM risks in heapsnapshot-near-heap-limit tests
joyeecheung Mar 15, 2021
e9c161c
http: fix double AbortSignal registration
Linkgoron Mar 12, 2021
8f18133
doc: use sentence case in issues.md headers
marsonya Mar 10, 2021
11d4585
crypto: fix header name
gengjiawen Mar 18, 2021
71fde07
doc: add Ayase-252 to triagers
Ayase-252 Mar 17, 2021
f07428a
test: remove skip for fixed test-benchmark-fs
Trott Mar 19, 2021
43c3b43
stream: make Readable.from performance better
wwwzbwcom Mar 5, 2021
9bc6fe7
test: remove references to unsupported AIX versions
richardlau Mar 20, 2021
f97a5dd
doc: use sentence-style capitlaztion in template header
Trott Mar 20, 2021
9defe10
doc: fix legacy stability indicator display
Trott Mar 20, 2021
cdfc1c8
child_process: cleanup AbortSignal duplication
Linkgoron Mar 19, 2021
44490af
test: relax Y2K38 check in test-fs-utimes-y2K38
richardlau Mar 20, 2021
0f2e142
tools: make genv8constants.py Python3-compatible
targos Mar 20, 2021
9557dda
stream: pipeline accept Buffer as a valid first argument
Linkgoron Mar 13, 2021
c0a424f
doc: clarify when child process 'spawn' event is *not* emitted
zenflow Mar 20, 2021
5d4c610
test: remove duplicated test for eventtarget
himself65 Mar 21, 2021
30bc2e4
doc: add examples for WHATWG URL objects
jasnell Mar 19, 2021
d9ab1d5
test: fix flaky test-vm-timeout-escape-promise-module-2
Trott Mar 20, 2021
aa529b7
test: fix ibmi skip message
tniessen Mar 19, 2021
3452618
tty: validate file descriptor to avoid int32 overflow
aduh95 Mar 19, 2021
7925938
crypto: fix DiffieHellman argument validation
aduh95 Mar 19, 2021
86bf341
test: fix deprecation warning in test-doctool-html
aduh95 Mar 22, 2021
dbc4804
tools: simplify eslint comma-dangle configuration
Trott Mar 20, 2021
b5879ef
tools: improve macos-firewall.sh output
Trott Mar 20, 2021
d5b472b
deps: upgrade npm to 7.7.0
ruyadorno Mar 23, 2021
33c35a3
test: add OpenSSL 3.0 checks to test-crypto-keygen
danbev Mar 22, 2021
5cdeb76
test: add OpenSSL 3.0 checks to tls-passphrase
danbev Mar 22, 2021
3ab223d
node-api: fix crash in finalization
mhdawson Mar 23, 2021
649e04c
deps: upgrade npm to 7.7.4
ruyadorno Mar 24, 2021
76ebc4b
test: increase wiggle room for memory in test-worker-resource-limits
Trott Mar 25, 2021
a6f21e2
doc: fix wording in outgoingMessage.write
tniessen Mar 24, 2021
e84252b
doc: reduce header nesting in async_hooks.md
Trott Mar 20, 2021
3925458
doc,tools: use only one level 1 header per page
Trott Mar 20, 2021
50fc6b9
crypto: clear errors in SignTraits::DeriveBits
panva Mar 19, 2021
2da532c
src: report idle time correctly
Mar 22, 2021
ca93e52
tools: simplify eslint comma-dangle configuration (tools)
Trott Mar 23, 2021
364c8ac
doc: update GOVERNANCE.md for TSC Charter changes
Trott Mar 24, 2021
a5bf7de
http2: fix setting options before handle exists
addaleax Mar 23, 2021
1c04327
http2: treat non-EOF empty frames like other invalid frames
addaleax Mar 23, 2021
ec82feb
deps: upgrade npm to 7.7.5
ruyadorno Mar 25, 2021
0fe3c7e
doc: spell out ICU acronym on first occurrence
Trott Mar 27, 2021
377830f
child_process: remove unused argument
Trott Mar 26, 2021
e256c4d
test: fix typeof comparison
Trott Mar 26, 2021
b7e7384
tools: improve valid-typeof lint rule
Trott Mar 26, 2021
bd87e19
src: fix typo in src code guide
tniessen Mar 28, 2021
ac60d01
doc: add more commands for cherry-picking and changelog to release docs
danielleadams Mar 17, 2021
d44b268
timers: fix arbitrary object clearImmediate errors
Linkgoron Mar 19, 2021
13ecff6
src: document newer values for --unhandled-rejections flag
glasser Mar 24, 2021
b6ad8e4
src: indent long help text properly
glasser Mar 25, 2021
659fc5d
doc: fix typos in lib/internal/bootstrap/pre_execution.js
marsonya Mar 8, 2021
d33f446
util: remove unreachable inspect code
Trott Mar 27, 2021
e60bd1a
perf_hooks: make Performance extend EventTarget
targos Mar 6, 2021
b0226b3
test: split promisified timers test for coverage purposes
Trott Mar 27, 2021
f2cef54
deps: upgrade npm to 7.7.6
ruyadorno Mar 29, 2021
2fd97ce
deps: v8 backport 9689b17687b
guybedford Mar 22, 2021
f09c033
deps: backport v8 f19142e6
guybedford Mar 22, 2021
71a7722
2021-03-31, Version 15.13.0 (Current)
ruyadorno Mar 30, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
child_process: add timeout to spawn and fork
Add support for timeout to spawn and fork.

Fixes: #27639

PR-URL: #37256
Reviewed-By: Benjamin Gruenbaum <[email protected]>
  • Loading branch information
Nitzan Uziely authored and ruyadorno committed Mar 24, 2021
commit 95aa032413800a660c0afffb205114e808619722
18 changes: 14 additions & 4 deletions doc/api/child_process.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,9 @@ controller.abort();
<!-- YAML
added: v0.5.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/37256
description: timeout was added.
- version: v15.11.0
pr-url: https://github.com/nodejs/node/pull/37325
description: killSignal for AbortSignal was added.
Expand Down Expand Up @@ -410,8 +413,8 @@ changes:
See [Advanced serialization][] for more details. **Default:** `'json'`.
* `signal` {AbortSignal} Allows closing the child process using an
AbortSignal.
* `killSignal` {string} The signal value to be used when the spawned
process will be killed by the abort signal. **Default:** `'SIGTERM'`.
* `killSignal` {string|integer} The signal value to be used when the spawned
process will be killed by timeout or abort signal. **Default:** `'SIGTERM'`.
* `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 @@ -423,6 +426,8 @@ changes:
* `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`.
* `timeout` {number} In milliseconds the maximum amount of time the process
is allowed to run. **Default:** `undefined`.
* Returns: {ChildProcess}

The `child_process.fork()` method is a special case of
Expand Down Expand Up @@ -478,6 +483,9 @@ if (process.argv[2] === 'child') {
<!-- YAML
added: v0.1.90
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/37256
description: timeout was added.
- version: v15.11.0
pr-url: https://github.com/nodejs/node/pull/37325
description: killSignal for AbortSignal was added.
Expand Down Expand Up @@ -528,8 +536,10 @@ changes:
normally be created on Windows systems. **Default:** `false`.
* `signal` {AbortSignal} allows aborting the child process using an
AbortSignal.
* `killSignal` {string} The signal value to be used when the spawned
process will be killed by the abort signal. **Default:** `'SIGTERM'`.
* `timeout` {number} In milliseconds the maximum amount of time the process
is allowed to run. **Default:** `undefined`.
* `killSignal` {string|integer} The signal value to be used when the spawned
process will be killed by timeout or abort signal. **Default:** `'SIGTERM'`.

* Returns: {ChildProcess}

Expand Down
29 changes: 24 additions & 5 deletions lib/child_process.js
Original file line number Diff line number Diff line change
Expand Up @@ -599,15 +599,14 @@ function abortChildProcess(child, killSignal) {


function spawn(file, args, options) {
const child = new ChildProcess();
options = normalizeSpawnArguments(file, args, options);
validateTimeout(options.timeout, 'options.timeout');
validateAbortSignal(options.signal, 'options.signal');
const killSignal = sanitizeKillSignal(options.killSignal);
const child = new ChildProcess();

if (options.signal) {
const signal = options.signal;
// Validate signal, if present
validateAbortSignal(signal, 'options.signal');
const killSignal = sanitizeKillSignal(options.killSignal);
// Do nothing and throw if already aborted
if (signal.aborted) {
onAbortListener();
} else {
Expand All @@ -626,6 +625,26 @@ function spawn(file, args, options) {
debug('spawn', options);
child.spawn(options);

if (options.timeout > 0) {
let timeoutId = setTimeout(() => {
if (timeoutId) {
try {
child.kill(killSignal);
} catch (err) {
child.emit('error', err);
}
timeoutId = null;
}
}, options.timeout);

child.once('exit', () => {
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
});
}

return child;
}

Expand Down
50 changes: 50 additions & 0 deletions test/parallel/test-child-process-fork-timeout-kill-signal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict';

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

{
// Verify default signal
const cp = fork(fixtures.path('child-process-stay-alive-forever.js'), {
timeout: 5,
});
cp.on('exit', mustCall((code, ks) => strictEqual(ks, 'SIGTERM')));
}

{
// Verify correct signal + closes after at least 4 ms.
const cp = fork(fixtures.path('child-process-stay-alive-forever.js'), {
timeout: 5,
killSignal: 'SIGKILL',
});
cp.on('exit', mustCall((code, ks) => strictEqual(ks, 'SIGKILL')));
}

{
// Verify timeout verification
throws(() => fork(fixtures.path('child-process-stay-alive-forever.js'), {
timeout: 'badValue',
}), /ERR_OUT_OF_RANGE/);

throws(() => fork(fixtures.path('child-process-stay-alive-forever.js'), {
timeout: {},
}), /ERR_OUT_OF_RANGE/);
}

{
// Verify abort signal gets unregistered
const signal = new EventTarget();
signal.aborted = false;

const cp = fork(fixtures.path('child-process-stay-alive-forever.js'), {
timeout: 6,
signal,
});
strictEqual(getEventListeners(signal, 'abort').length, 1);
cp.on('exit', mustCall(() => {
strictEqual(getEventListeners(signal, 'abort').length, 0);
}));
}
50 changes: 50 additions & 0 deletions test/parallel/test-child-process-spawn-timeout-kill-signal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict';

const { mustCall } = require('../common');
const { strictEqual, throws } = require('assert');
const fixtures = require('../common/fixtures');
const { spawn } = require('child_process');
const { getEventListeners } = require('events');

const aliveForeverFile = 'child-process-stay-alive-forever.js';
{
// Verify default signal + closes
const cp = spawn(process.execPath, [fixtures.path(aliveForeverFile)], {
timeout: 5,
});
cp.on('exit', mustCall((code, ks) => strictEqual(ks, 'SIGTERM')));
}

{
// Verify SIGKILL signal + closes
const cp = spawn(process.execPath, [fixtures.path(aliveForeverFile)], {
timeout: 6,
killSignal: 'SIGKILL',
});
cp.on('exit', mustCall((code, ks) => strictEqual(ks, 'SIGKILL')));
}

{
// Verify timeout verification
throws(() => spawn(process.execPath, [fixtures.path(aliveForeverFile)], {
timeout: 'badValue',
}), /ERR_OUT_OF_RANGE/);

throws(() => spawn(process.execPath, [fixtures.path(aliveForeverFile)], {
timeout: {},
}), /ERR_OUT_OF_RANGE/);
}

{
// Verify abort signal gets unregistered
const controller = new AbortController();
const { signal } = controller;
const cp = spawn(process.execPath, [fixtures.path(aliveForeverFile)], {
timeout: 6,
signal,
});
strictEqual(getEventListeners(signal, 'abort').length, 1);
cp.on('exit', mustCall(() => {
strictEqual(getEventListeners(signal, 'abort').length, 0);
}));
}