Skip to content

SIGINT is not handled when a short-lived process is run in watch-mode#51466

@azrsh

Description

@azrsh

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?

  1. Write some short-lived script and save it to index.js.
console.log("short-lived!");
  1. 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.jsconsole.log("short-lived!"); $ node test.jsshort-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^C

I 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.

constexitCode=awaitkillAndWait(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.

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.

constonExit=once(child,'exit');
child.kill(signal);
const{0: exitCode}=awaitonExit;

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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    watch-modeIssues and PRs related to watch mode

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions