nodemon: Nodemon doesn't wait for `SIGUSR2` graceful shutdown?

  • nodemon -v: 2.0.9
  • node -v: v16.1.0
  • Operating system/terminal environment: macOS Catalina, iTerm 2
  • Using Docker? What image: Yes, but I have a non-docker breaking example
  • Command you ran: yarn run nodemon watch.js

I’m trying to write a shutdown handler to gracefully close my mariadb sql client pool, but it never works because the script is killed too soon. I copied the example from the README and changed the signal to SIGTERM but it never lets the shutdown function finish.

If I manually send a kill -s SIGUSR2 <pid> then it will wait for the shutdown script, but nodemon doesn’t wait.

My shutdown function uses async/await, but I was able to reproduce with out it. All the below info applies to async/await too (meaning it works with manual kill but not nodemon).

Expected behaviour

The script doesn’t get killed by nodemon before it can gracefully shut itself down

Actual behaviour

Nodemon kills the script before my SIGUSR2 script can finish

Steps to reproduce

create a file watch.js:

process.stdin.read();

process.once('SIGUSR2', (signal) => {
  for (let i = 1; i <= 10000; i++) {
    console.log(i);
  }

  process.kill(process.pid, signal);
});

Save watch.js to trigger a restart and notice that the logs never reach 10,000 (for me it never goes past 4k). Send a manual kill -s SIGUSR2 <pid> and notice that the logs go to 10k, the script ends and then nodemon restarts it.


If applicable, please append the --dump flag on your command and include the output here ensuring to remove any sensitive/personal details or tokens.

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 7
  • Comments: 32 (7 by maintainers)

Commits related to this issue

Most upvoted comments

I used git bisect and determined that this is the breaking commit: 47dfb8be3ff06184793a55d32db4b6171fa2993f.

The biggest change I see in that commit is the addition of child.kill(signal); before it calls waitForSubProcesses. If I commend out that line on master then nodemon waits for my SIGUSR2 function to complete as I expect.

@lukepolo downgrade nodemon to 2.0.1 same for nodemon-webpack-plugin:

    "nodemon": "2.0.1",
    "nodemon-webpack-plugin": "4.2.1",

After this my above example correctly waits for the cleanup: Change process.once into process.on

start
[nodemon] still waiting for 1 subprocess(es) to finish...
[nodemon] still waiting for 1 subprocess(es) to finish...
end

@remy do you have time for this?

Any workarounds for the time being? It’s not super critical but would be nice!

I had a same problem, so I have been stick on version 2.0.1 too

@remy Looking through some of the other issues here, I saw your comment here.

I just tested directly called nodemon instead of going through npm run or npx. It seems it’s properly waiting for the graceful exit to finish before restarting. What’s wild is that for version 2.0.1, it properly works through npm run or npx. Testing version 2.0.2 causes the bug to pop up. My guess is there must have been some code that was removed in 2.0.2 to make sure the process properly exited before starting the new process.

process.once('SIGUSR2',  () => {
      while (true) {
        console.log(Date.now());
      }
    });

This does indeed log for a long time.

Then asynchronously waiting for cleanup to be finished:

process.once('SIGUSR2', async () => {
     console.log('start');
     await asyncCloseCallback();
     console.log('end');
   });

This indeed logs only the “start” and restarts in middle of cleanup.