Repository navigation
SIGINT is not handled when a short-lived process is run in watch-mode #51466
Description
Version
v20.11.0
Platform
Linux hostname 6.5.7-arch1-1 #\1 SMP PREEMPT_DYNAMIC Tue, 10 Oct 2023 21:10:21 +0000 x86_64 GNU/Linux
Subsystem
No response
What steps will reproduce the bug?
- Write some short-lived script and save it to
index.js.
console.log("short-lived!");- Run this script in watch-mode.
$ node --watch index.js
(node:1191877) ExperimentalWarning: Watch mode is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
short-lived!
Completed running 'index.js'After following the above steps, you will no longer be able to terminate the Node.js process in watch-mode with SIGINT or SIGTERM.
How often does it reproduce? Is there a required condition?
If you follow the steps, it will always reproduce.
What is the expected behavior? Why is that the expected behavior?
A Node.js process in watch-mode will be terminated if we send SIGINT or SIGTERM to the process, such as with Ctrl + C.
What do you see instead?
$ vim index.js
$ cat index.js
console.log("short-lived!");
$ node test.js
short-lived!
$ node --watch index.js
(node:1191877) ExperimentalWarning: Watch mode is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
short-lived!
Completed running 'index.js'
^C^C^C^C^C^CI input Ctrl + C but the input is ignored.
Additional information
Mechanism of this behavior
The cause of this behavior is the killAndWait function located in /lib/internal/main/watch_mode.js:69.
Node.js process in watch-mode triggers a signal handler when it receives SIGINT or SIGTERM. In this signal handler, the killAndWait function is called as shown below.
node/lib/internal/main/watch_mode.js
Line 134 in c25878d
| const exitCode = await killAndWait(signal, true); |
At this time, since the argument force of the killAndWait function is set to true, processing continues without satisfying the condition in the code path below of the killAndWait function.
node/lib/internal/main/watch_mode.js
Lines 74 to 76 in c25878d
| if ((child.killed || exited) && !force) { | |
| return; | |
| } |
As a result, the killAndWait function will wait for a process that has already terminated to terminate. In other words, the wait never ends.
node/lib/internal/main/watch_mode.js
Lines 77 to 79 in c25878d
| const onExit = once(child, 'exit'); | |
| child.kill(signal); | |
| const { 0: exitCode } = await onExit; |
My proposed modifications
Modify the killAndWait function so that if exited is true, return the killAndWait function regardless of the value of the argument force.
If you accept this modification, I can create a PR!
Thank you!
Activity
watch: handle signal correctly in short-lived process
debadree25 commentedon Jan 15, 2024
Doing CtrlC is correctly terminating the process for me 🤔
duncanchiu409 commentedon Jan 15, 2024
Ctrl C is terminating the process for me.
azrsh commentedon Jan 16, 2024
Oh! The
--watchoption was working fine in my environment as well.Sorry, I had oversimplified the reproduction conditions and made a mistake. We can actually reproduce this by specifying the entry point script in
--watch-path.Also, this behavior only seems to work on Linux. Could not reproduce on Mac.
duncanchiu409 commentedon Jan 16, 2024
@azrsh Could re-produce the issue at v22.0.0-pre. However, I found your use of --watch-path is wrong. The correct command should be "node --watch-path=./ index.js". If you run my command, It should work as fine. Though, I could see a possible new issue on flag parsing. For example, not correct option on --watch-path should be stopped.
duncanchiu409 commentedon Jan 16, 2024
Details on https://nodejs.org/docs/latest/api/cli.html#--watch-path
azrsh commentedon Jan 17, 2024
In my environment, the command certainly works fine.
Does it mean that specifying a file instead of a directory in
--watch-pathis wrong?I didn't find any such limitation written in the Node.js Command-line API documentation...
github-actions commentedon May 24, 2026
This issue has been marked as stale due to 210 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
github-actions commentedon Jun 24, 2026
This issue has been automatically closed after 30 days of inactivity following its stale status (no activity for a total of 240 days).
If this is still relevant, feel free to reopen it or leave a comment with additional details so we can continue the discussion.