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.

Incorrect handling of SIGHUP

See original GitHub issue

I think the implementation of handling of SIGHUP is not 100% correct.

The proper handling of SIGHUP is to terminate the application and its children, but nodemon restarts the child instead.

The changes in SIGHUP handling were introduced with PR #1167 (commit 30f999a0). This commit introduced the feature to allow restarting child by sending SIGHUP to nodemon process. While the feature itself if fine, the choice of the signal, in my opinion, is not 100% correct. It think it would be better to always use SIGUSR2 for triggering restart. The details are below.

Expected behaviour

nodemon should terminate its child and itself upon receiving SIGHUP signal.

Actual behaviour

nodemon restarts the child.

Steps to reproduce

Use the following application:

const fs = require('fs')

fs.writeFileSync('signals.log', 'Log start\n')

function log (msg) {
    fs.writeFileSync('signals.log', msg + '\n', { flag: 'a' })
}

var counter = 1
setInterval(() => log(counter++), 1000)

With Visual Studio Code

  1. Launch VS Code, open folder with the nodemon repository
  2. Save the sample code as signals-test.js
  3. Open integrated terminal (<kbd>Ctrl</kbd> + <kbd>`</kbd>)
  4. Run the following command:
node bin/nodemon.js signals-handler.js   
  1. For convenience, open signals.log in VS Code editor (it automatically reloads log file after changes). Alternatively, run the following command in another terminal:
tail -f signals.log
  1. Close the integrated VS Code terminal by clicking the trashcan icon

Notice the updates to signals.log file are restarted and continue from the background instance of the signals-test.js.

With ssh

  1. Install and configure ssh server
  2. Connect to the machine via ssh. It is ok to connect to localhost for this test.
  3. Change dir to the nodemon repository
  4. Run the following command in ssh session:
node bin/nodemon.js signals-handler.js   
  1. In another terminal also change dir to nodemon repository and run the following command:
tail -f signals.log
  1. In yet another terminal kill the ssh client:
pkill -f ssh localhost

Notice the updates to signals.log file are restarted and continue from the background instance of the signals-test.js. Nodemon behaves like nohup utility for applications launched in ssh session.

Environment

nodemon: 2.0.2 (from sources in master) node -v: v12.14.0 Operating system/terminal environment: Ubuntu 18.04.3 LTS

Analysis

According to man 7 signal, SIGHUP is sent when “Hangup detected on controlling terminal or death of controlling process”. Similar description can be found in Node documentation.

Historically SIGHUP was useless for daemons because they have no controlling terminal. SIGHUP was then reused for triggering the reloading of daemon configs. However, the original handling is still valid and probably required for non-daemon apps, specifically, for applications started in the terminal.

How to test this behavior: run the sample code in the VS code terminal or via ssh directly, without nodemon. Then close the terminal or kill the client connection, just like described in the “Steps to reproduce section above”. Notice that the signals.log file is updated while terminal is open and updates stop when the terminal is closed. This is in the contrast to the launching the same code from under the nodemon.

Proposed fix

I’ve made a PR with one variant of the fix. It contains the following changes:

  1. Handle only SIGUSR2 to trigger reload
  2. On SIGHUP quit with corresponding error code
  3. Also added tests for SIGHUP in separate commit

Since this is a breaking change (though a minor one), I would like to propose alternative solutions:

  1. Specify signal for reload as a separate command line and config parameter, keep the current behavior as default if parameter is not specified. The disadvantage of this approach is that with VS Code and ssh the default behavior would be counterintuitive.
  2. Add a parameter to ignore reload signal and keep the current behavior as default. Same disadvantage as 1.

Alternatively, the parameter can be used to switch to old (current) behavior.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:3
  • Comments:19 (12 by maintainers)

github_iconTop GitHub Comments

2reactions
axxiecommented, May 3, 2020

Still not stale

1reaction
TheLuddcommented, Apr 14, 2020

I found this issue because it also gives me trouble. I use tmux when developing, and in some windows I run nodemon to run my web server in dev mode. When executing :kill-session in tmux it sends SIGHUP to all processes. What then happens is that nodemon restarts and the window that nodemon is in is destroyed. But my server is still running.

So now I have an “invisible” process running and if I try to start up a new dev session it says that the port I use is already in use.

So what should happen in my specific case would be that 1 tmux sends SIGHUP to nodemon 2 nodemon sends SIGHUP to my application that can listen for this and stop itself 3 nodemon exists gracefully

PS stalebot is a bit aggressive IMHO.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SIGHUP strange behavior - Unix & Linux Stack Exchange
I am running a process from bash without & and any redirection i.e like ./foo . The process is running while(1) i.e it...
Read more >
Unable to catch SIGHUP signal - Stack Overflow
I am facing a strange problem while handling the SIGHUP signal. I need to execute some commands in interactive mode.
Read more >
A background process can explicitly ignore SIGHUP The ...
The problem with SIGHUP is that a background process can't explicitly ignore SIGHUP, it can only implicitly ignore it. If you send SIGHUP...
Read more >
POSIX signals
The SIGHUP signal is sent to a process when its controlling terminal is closed. It was originally designed to notify the process of...
Read more >
Signals in prod: dangers and pitfalls - Meta for Developers
The problem is that in any large, mature codebase, that is difficult. SIGHUP is not like a tightly controlled IPC call for which...
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