src: add --process-timeout=N - #66138
Merged
Merged
Conversation
Collaborator
|
Review requested:
|
jasnell
force-pushed
the
jasnell/process-timeout
branch
2 times, most recently
from
September 19, 2026 17:54
7ae9d38 to
b846293
Compare
jasnell
force-pushed
the
jasnell/process-timeout
branch
from
September 19, 2026 19:25
b846293 to
f0d5d08
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #66138 +/- ##
==========================================
- Coverage 90.31% 90.28% -0.03%
==========================================
Files 789 789
Lines 272878 273229 +351
Branches 52112 52183 +71
==========================================
+ Hits 246444 246695 +251
- Misses 16909 16963 +54
- Partials 9525 9571 +46
🚀 New features to boost your workflow:
|
This comment was marked as outdated.
This comment was marked as outdated.
jasnell
force-pushed
the
jasnell/process-timeout
branch
from
September 20, 2026 15:37
f0d5d08 to
4a3abcd
Compare
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Member
Author
|
@nodejs/build ... this is currently blocked by the persistent windows ci failure |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Contributor
|
The
notable-change
Please suggest a text for the release notes if you'd like to include a more detailed summary, then proceed to update the PR description with the text or a link to the notable change suggested text comment. Otherwise, the commit will be placed in the Other Notable Changes section. |
jasnell
force-pushed
the
jasnell/process-timeout
branch
from
September 23, 2026 18:30
4a3abcd to
1a5f525
Compare
Putting a time limit on a Node.js process is common in many
use cases, but each of the common approaches are generally
flawed.
OS and CI timeouts are inconsistent and blind. Every OS flavor
handles process timeouts in different ways. Stock macOS and
Windows do not ship coreutils `timeout`, etc. None of the options
can explain why the process was still running or what exactly
was interrupted. Using setTimeout only fires when the event loop
is free so it misses busy loops and thread blocks and cannot
see the stack. Diagnostics triggered by signal have the same
problem.
This introduces a `--process-timeout` that should work
consistently across all runtimes. A native watchdog thread
interrupts the main thread, even in the middle of running
code. It prints the JavaScript stack (if any) and resources
keeping the event loop alive (if any), and can optionally
print a full diagnostic report. The process exits with a
distinct code (124). If the main thread is stuck in native
code, the process still exits.
$ node --process-timeout=10s -e "while(true) {}"
(node:483970) Process timed out after 10s (--process-timeout). Exiting with code 124.
Main thread was executing JavaScript:
at [eval]:1:1
at runScriptInThisContext (node:internal/vm:219:10)
at node:internal/process/execution:485:12
at [eval]-wrapper:6:24
at runScriptInContext (node:internal/process/execution:483:60)
at evalFunction (node:internal/process/execution:317:30)
at evalTypeScript (node:internal/process/execution:329:3)
at node:internal/main/eval_string:71:3
No resources keeping the event loop alive were found.
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
jasnell
force-pushed
the
jasnell/process-timeout
branch
from
September 23, 2026 21:26
1a5f525 to
823ccda
Compare
This comment was marked as outdated.
This comment was marked as outdated.
Collaborator
trivikr
approved these changes
Sep 25, 2026
Collaborator
|
Landed in 823d229 |
HoonDongKang
pushed a commit
to HoonDongKang/node
that referenced
this pull request
Sep 28, 2026
Putting a time limit on a Node.js process is common in many
use cases, but each of the common approaches are generally
flawed.
OS and CI timeouts are inconsistent and blind. Every OS flavor
handles process timeouts in different ways. Stock macOS and
Windows do not ship coreutils `timeout`, etc. None of the options
can explain why the process was still running or what exactly
was interrupted. Using setTimeout only fires when the event loop
is free so it misses busy loops and thread blocks and cannot
see the stack. Diagnostics triggered by signal have the same
problem.
This introduces a `--process-timeout` that should work
consistently across all runtimes. A native watchdog thread
interrupts the main thread, even in the middle of running
code. It prints the JavaScript stack (if any) and resources
keeping the event loop alive (if any), and can optionally
print a full diagnostic report. The process exits with a
distinct code (124). If the main thread is stuck in native
code, the process still exits.
$ node --process-timeout=10s -e "while(true) {}"
(node:483970) Process timed out after 10s (--process-timeout). Exiting with code 124.
Main thread was executing JavaScript:
at [eval]:1:1
at runScriptInThisContext (node:internal/vm:219:10)
at node:internal/process/execution:485:12
at [eval]-wrapper:6:24
at runScriptInContext (node:internal/process/execution:483:60)
at evalFunction (node:internal/process/execution:317:30)
at evalTypeScript (node:internal/process/execution:329:3)
at node:internal/main/eval_string:71:3
No resources keeping the event loop alive were found.
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: nodejs#66138
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
aduh95
pushed a commit
that referenced
this pull request
Sep 28, 2026
Putting a time limit on a Node.js process is common in many
use cases, but each of the common approaches are generally
flawed.
OS and CI timeouts are inconsistent and blind. Every OS flavor
handles process timeouts in different ways. Stock macOS and
Windows do not ship coreutils `timeout`, etc. None of the options
can explain why the process was still running or what exactly
was interrupted. Using setTimeout only fires when the event loop
is free so it misses busy loops and thread blocks and cannot
see the stack. Diagnostics triggered by signal have the same
problem.
This introduces a `--process-timeout` that should work
consistently across all runtimes. A native watchdog thread
interrupts the main thread, even in the middle of running
code. It prints the JavaScript stack (if any) and resources
keeping the event loop alive (if any), and can optionally
print a full diagnostic report. The process exits with a
distinct code (124). If the main thread is stuck in native
code, the process still exits.
$ node --process-timeout=10s -e "while(true) {}"
(node:483970) Process timed out after 10s (--process-timeout). Exiting with code 124.
Main thread was executing JavaScript:
at [eval]:1:1
at runScriptInThisContext (node:internal/vm:219:10)
at node:internal/process/execution:485:12
at [eval]-wrapper:6:24
at runScriptInContext (node:internal/process/execution:483:60)
at evalFunction (node:internal/process/execution:317:30)
at evalTypeScript (node:internal/process/execution:329:3)
at node:internal/main/eval_string:71:3
No resources keeping the event loop alive were found.
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: #66138
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
aduh95
pushed a commit
that referenced
this pull request
Sep 28, 2026
Putting a time limit on a Node.js process is common in many
use cases, but each of the common approaches are generally
flawed.
OS and CI timeouts are inconsistent and blind. Every OS flavor
handles process timeouts in different ways. Stock macOS and
Windows do not ship coreutils `timeout`, etc. None of the options
can explain why the process was still running or what exactly
was interrupted. Using setTimeout only fires when the event loop
is free so it misses busy loops and thread blocks and cannot
see the stack. Diagnostics triggered by signal have the same
problem.
This introduces a `--process-timeout` that should work
consistently across all runtimes. A native watchdog thread
interrupts the main thread, even in the middle of running
code. It prints the JavaScript stack (if any) and resources
keeping the event loop alive (if any), and can optionally
print a full diagnostic report. The process exits with a
distinct code (124). If the main thread is stuck in native
code, the process still exits.
$ node --process-timeout=10s -e "while(true) {}"
(node:483970) Process timed out after 10s (--process-timeout). Exiting with code 124.
Main thread was executing JavaScript:
at [eval]:1:1
at runScriptInThisContext (node:internal/vm:219:10)
at node:internal/process/execution:485:12
at [eval]-wrapper:6:24
at runScriptInContext (node:internal/process/execution:483:60)
at evalFunction (node:internal/process/execution:317:30)
at evalTypeScript (node:internal/process/execution:329:3)
at node:internal/main/eval_string:71:3
No resources keeping the event loop alive were found.
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: #66138
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
nodejs-github-bot
added a commit
that referenced
this pull request
Oct 5, 2026
Notable changes: benchmark: * (SEMVER-MINOR) add http header validator benchmark (James M Snell) #66334 buffer: * (SEMVER-MINOR) add isLatin1 (James M Snell) #66298 * (SEMVER-MINOR) add isLatin1 (James M Snell) #66298 * (SEMVER-MINOR) add Buffer.stringLength() (Matteo Collina) #66064 build, doc: * move to redesign (Aviv Keller) #62045 http: * (SEMVER-MINOR) add isValidHeaderName() and isValidHeaderValue() (James M Snell) #66334 http2: * (SEMVER-MINOR) add new connectionWindowSize option (Tim Perry) #65619 lib: * (SEMVER-MINOR) fix stream loading bug in node:bench (James M Snell) #66114 perf_hooks: * (SEMVER-MINOR) fix truncation of monitorEventLoopDelay() resolution (James M Snell) #66115 * (SEMVER-MINOR) allow RecordableHistogram to record 0 (James M Snell) #66114 * (SEMVER-MINOR) add histogram.diff() (James M Snell) #66099 * (SEMVER-MINOR) report histogram memory to V8 (James M Snell) #66099 * (SEMVER-MINOR) add histogram.snapshot() (James M Snell) #66099 * (SEMVER-MINOR) add histogram export format version 2 (James M Snell) #66098 * (SEMVER-MINOR) harden histogram CBOR import validation (James M Snell) #66098 process: * (SEMVER-MINOR) graduate process.ref/unref from experimental (James M Snell) #66213 sqlite: * (SEMVER-MINOR) rename DatabaseSync and StatementSync (Guilherme Araújo) #65988 src: * (SEMVER-MINOR) add --process-timeout=N (James M Snell) #66138 * (SEMVER-MINOR) expose size and count in heap profile output (Ilyas Shabi) #65737 * (SEMVER-MINOR) let embedders exempt linked bindings from the addon permission (Shelley Vohr) #66067 test: * deflake sliding window histogram test (James M Snell) #66132 PR-URL: #66546
aduh95
pushed a commit
that referenced
this pull request
Oct 6, 2026
Notable changes: buffer: * (SEMVER-MINOR) add isLatin1 (James M Snell) #66298 * (SEMVER-MINOR) add Buffer.stringLength() (Matteo Collina) #66064 build, doc: * move to redesign (Aviv Keller) #62045 http: * (SEMVER-MINOR) add isValidHeaderName() and isValidHeaderValue() (James M Snell) #66334 http2: * (SEMVER-MINOR) add new connectionWindowSize option (Tim Perry) #65619 perf_hooks: * (SEMVER-MINOR) fix truncation of monitorEventLoopDelay() resolution (James M Snell) #66115 * (SEMVER-MINOR) allow RecordableHistogram to record 0 (James M Snell) #66114 * (SEMVER-MINOR) add histogram.diff() (James M Snell) #66099 * (SEMVER-MINOR) report histogram memory to V8 (James M Snell) #66099 * (SEMVER-MINOR) add histogram.snapshot() (James M Snell) #66099 * (SEMVER-MINOR) add histogram export format version 2 (James M Snell) #66098 * (SEMVER-MINOR) harden histogram CBOR import validation (James M Snell) #66098 process: * (SEMVER-MINOR) graduate process.ref/unref from experimental (James M Snell) #66213 sqlite: * (SEMVER-MINOR) rename DatabaseSync and StatementSync (Guilherme Araújo) #65988 src: * (SEMVER-MINOR) add --process-timeout=N (James M Snell) #66138 * (SEMVER-MINOR) expose size and count in heap profile output (Ilyas Shabi) #65737 * (SEMVER-MINOR) let embedders exempt linked bindings from the addon permission (Shelley Vohr) #66067 PR-URL: #66546
aduh95
pushed a commit
that referenced
this pull request
Oct 6, 2026
Notable changes: buffer: * (SEMVER-MINOR) add isLatin1 (James M Snell) #66298 * (SEMVER-MINOR) add Buffer.stringLength() (Matteo Collina) #66064 build, doc: * move to redesign (Aviv Keller) #62045 doc: * promote Alpine Linux to tier 2 support (Stewart X Addison) #63737 http: * (SEMVER-MINOR) add isValidHeaderName() and isValidHeaderValue() (James M Snell) #66334 http2: * (SEMVER-MINOR) add new connectionWindowSize option (Tim Perry) #65619 perf_hooks: * (SEMVER-MINOR) fix truncation of monitorEventLoopDelay() resolution (James M Snell) #66115 * (SEMVER-MINOR) allow RecordableHistogram to record 0 (James M Snell) #66114 * (SEMVER-MINOR) add histogram.diff() (James M Snell) #66099 * (SEMVER-MINOR) add histogram.snapshot() (James M Snell) #66099 * (SEMVER-MINOR) harden histogram CBOR import validation (James M Snell) #66098 process: * (SEMVER-MINOR) graduate process.ref/unref from experimental (James M Snell) #66213 sqlite: * (SEMVER-MINOR) rename DatabaseSync and StatementSync (Guilherme Araújo) #65988 src: * (SEMVER-MINOR) add --process-timeout=N (James M Snell) #66138 * (SEMVER-MINOR) expose size and count in heap profile output (Ilyas Shabi) #65737 * (SEMVER-MINOR) let embedders exempt linked bindings from the addon permission (Shelley Vohr) #66067 PR-URL: #66546
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Putting a time limit on a Node.js process is common in many use cases, but each of the common approaches are generally flawed.
OS and CI timeouts are inconsistent and blind. Every OS flavor handles process timeouts in different ways. Stock macOS and Windows do not ship coreutils
timeout, etc. None of the options can explain why the process was still running or what exactly was interrupted. Using setTimeout only fires when the event loop is free so it misses busy loops and thread blocks and cannot see the stack. Diagnostics triggered by signal have the same problem.This introduces a
--process-timeoutthat should work consistently across all runtimes. A native watchdog thread interrupts the main thread, even in the middle of running code. It prints the JavaScript stack (if any) and resources keeping the event loop alive (if any), and can optionally print a full diagnostic report. The process exits with a distinct code (124). If the main thread is stuck in native code, the process still exits.Compare with using
timeoutwhich produces no diagnostic output:This needs careful review and evaluation before considering landing. There are ways that the timeout can interplay with various other options (like
--watch, and--inspect). I've made some preliminary decisions on it but they need to be reviewed.We will need to evaluate flakiness of the tests... there are a couple risks to look out for: