Toward a better signal handling
See original GitHub issuenodemon -v: 2.0.3node -v: v13.13.0- Operating system/terminal environment: Void Linux / kitty + fish.
- Using Docker? Nop.
- Command you ran:
npx nodemon
This is not a bug, but rather a discussion on how to handle signals. Heavely related to #1667.
Actual behaviour
Currently, it’s quite a mess ( ͡° ͜ʖ ͡°).
Basics
to close, to end, to exit, to quit, to stop, to terminate, to shut down, a bit confusing isn’t it?
Let me quote the official documentation.
SIGTERM:
It is the normal way to politely ask a program to terminate. The shell command kill generates SIGTERM by default.
SIGQUIT:
Certain kinds of cleanups are best omitted in handling SIGQUIT.
SIGHUP:
[…] used to report that the user’s terminal is disconnected
Expected behaviour
This is rather debatable, but here I go.
When nodmeon receives SIGINT or SIGHUP, it should pass the signal to the child process, and if the process does not quit after X seconds, nodemon should ignore the signal. This way, the child process is free to do whatever it wants (e.g. reload config or gracefully quit). If the child stops before the timeout, nodemon should also stops. This should solves #1661. Also, if SIGINT is received before timeout, SIGKILL is sent to the child. This way, the user can forcefully quit with two ^C.
When nodemon receives SIGTERM, it should pass the signal to the child process, and if the process does not quit after X seconds, send SIGKILL to the child, then quit nodemon. This is the behaviour of systemd and it simplifies integration with system’s init.
When nodmeon receives SIGQUIT, it should immediatly SIGKILL the child, then quit nodemon. This way, no cleaning is done by the child.
Also, the restart should be interpretad more as a realod. This way, we can specify a reloadSignal (set to SIGHUP by default) which is sent each time a change is detected by watch or user types restart. nodemon should not use (implicitely at least) SIGUSR2 since it’s a user-defined condition (aka. reserved for the child process for other tasks).
We should also add a timeout config to set the value used by nodemon.
WDYT?
Issue Analytics
- State:
- Created 3 years ago
- Reactions:4
- Comments:19 (8 by maintainers)

Top Related StackOverflow Question
Just a data point here: I remember using a program (though I can’t remember what it is) that printed out something like “attempting to shut down gracefully, press Ctrl+C again to force quit” when I pressed Ctrl+C. And I have used software before that didn’t seem to correctly shut down when I press Ctrl+C, and in those cases, I usually mash Ctrl+C until the software seems to listen (I can’t be the only one who does this).
So IMO the suggestion of first sending SIGINT (on first Ctrl+C), then SIGKILL (on second or maybe even third Ctrl+C) makes complete sense.
Let’s start with
SIGHUP. This signal is quite problematic because it has two roles in the UNIX world.Reloading. SSHd:
NGiИX:
systemd:
However, the second role applies to only daemonized processes because deamons are detached from their terminal. So the system will never send this signal to them.
In our case, nodemon is NOT a daemon but rather a foreground process, so it should not interpret
SIGHUPas a reload, but rather an exit.Now,
SIGUSR1(or 2) to reload the children?Also, after thinking about it, it’s useless for nodemon to listen to
SIGQUIT, so forget my previous recommendation on this signal. That being said, my recommendation aboutSIGINTremains valid.@remy, I understand. Changing the
SIGUSR2toSIGHUPnow would be too drastic. So forget about what I’ve said. The current behaviour is ok (send signal fromsignal).One last thing. The command “rs” should be renamed to “rl” (reload). Strictly speaking, a restart is sending SIGTERM, SIGKILL after timeout if child does not exit, then start the child (systemd).
Version 2: