question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Toward a better signal handling

See original GitHub issue
  • nodemon -v: 2.0.3
  • node -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:open
  • Created 3 years ago
  • Reactions:4
  • Comments:19 (8 by maintainers)

github_iconTop GitHub Comments

6reactions
bduffanycommented, Dec 14, 2020

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.

3reactions
concatimecommented, Apr 30, 2020

Let’s start with SIGHUP. This signal is quite problematic because it has two roles in the UNIX world.

  1. […] used to report that the user’s terminal is disconnected

  2. Reloading. SSHd:

    rereads its configuration file when it receives a hangup signal, SIGHUP, by executing itself with the name and options it was started with

    NGiИX:

    HUP changing configuration, […] starting new worker processes with a new configuration, graceful shutdown of old worker processes

    systemd:

    /bin/kill -HUP $MAINPID Note however that reloading a daemon by sending a signal (as with the example line above) is usually not a good choice, because this is an asynchronous operation and hence not suitable to order reloads of multiple services against each other. It is strongly recommended to set ExecReload= to a command that not only triggers a configuration reload of the daemon, but also synchronously waits for it to complete.

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 SIGHUP as a reload, but rather an exit.

Now,

  1. Should nodemon listen on 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 about SIGINT remains valid.

@remy, I understand. Changing the SIGUSR2 to SIGHUP now would be too drastic. So forget about what I’ve said. The current behaviour is ok (send signal from signal).

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:

(SIGUSR1?)/“rl”/watch ==> nodemon ==> `signal` (SIGUSR2 by default) ==> child
*if child exits:
	start child
*endif
-----------------------------------------------
SIGINT ==> nodemon ==> SIGINT ==> child
*if SIGINT before $timeout:
                   ==> SIGKILL ==> child
*endif
*if child exits before $timeout:
	exit nodemon
*endif
-----------------------------------------------
SIGHUP|TERM ==> nodemon ==> SIGTERM ==> child
*if ! child exits before $timeout:
                        ==> SIGKILL ==> child
*endif
exit nodemon
Read more comments on GitHub >

github_iconTop Results From Across the Web

CSCI 4061: Signals and Signal Handlers
Signals are an old system of communication to convey limited information to a process: Interprocess Communication (IPC).
Read more >
The Methods toward Improving Communication Performance ...
The Methods toward Improving Communication Performance in Transparent Radio Frequency Signals · 1. Introduction · 2. Low-Power RF Transmitter · 3. Low-Power RF ......
Read more >
Signals in prod: dangers and pitfalls - Meta for Developers
In this blog post, Chris Down, a Kernel Engineer at Meta, discusses the pitfalls of using Linux signals in the Linux production environments...
Read more >
Toward a Cognitive View of Signalling Theory: Individual ...
Contributing a cognitive perspective of signal attention and interpretation, alongside the introduction of signal sets, we provide a more ...
Read more >
Inflammasome activation and regulation: toward a better ...
For example, the NLRP3 inflammasome in macrophages can be activated by a multitude of viruses and viral proteins, such as the hepatitis C...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found