-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nodemon doesn't wait for SIGUSR2
graceful shutdown?
#1889
Comments
I can reproduce on a linux system as well
|
That's correct. nodemon sends the SIGUSR2 signal to the subprocess and if it doesn't exit within a predefined time frame, it'll force quit the sub process. Otherwise your sub process could be stuck hanging and nodemon would never be able to restart it. |
Can the "predefined time frame" be changed? I can't even close a database pool to a local db before nodemon kills it and crashes the database. This is a "guess I can't use nodemon" issue for me. |
🤔 thinking back, I originally wrote it so that if you trapped the signal from nodemon then your script would be responsible for stopping. Logic has changed over the 11 years I've been developing nodemon so maybe it's been lost along the way. Though quickly looking this evening, it looks as I'd expect:
|
That's what I assumed would happen based on the README:
I did some timings locally and nodemon kills it after ~50ms for me. That seems really short. process.stdin.read();
process.once('SIGUSR2', async(signal) => {
while(true) {
console.log(Date.now());
}
}); |
I'm looking into this more, I think it's a bug. The code for I added some
I'm assuming that the "subprocess" here means the script that nodemon is running. |
I used git bisect and determined that this is the breaking commit: 47dfb8b. The biggest change I see in that commit is the addition of |
And with it comments out and without the sub process handling the exit itself does the spawned sub process still restart? In theory, the kill signal is still |
meaning don't call process.once('SIGUSR2', (signal) => {
for (let i = 1; i <= 10000; i++) {
console.log(i);
}
});
I also tried with a async/await based delay wait 1 second and it also works without const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
process.once('SIGUSR2', async (signal) => {
console.log(`watch.js: ${signal} start`);
await delay(1000);
console.log(`watch.js: ${signal} stop`);
process.kill(process.pid, signal);
});
If I use an infinite loop, it looks like nodemon does not kill it, it just waits forever: process.once('SIGUSR2', (signal) => {
while(true) {
console.log(Date.now());
}
}); |
Sorry, I wasn't clear at all (!). If you remove the hook in your subprocess that listens for |
Without a console.log('watch.js: process started');
process.stdin.read();
|
Right, well first of all: excellent job in following up and digging. That's definitely a regression and I'll see if I can find time this week to sort it (or happy to take a pr). |
Remove underscore and express validator Use nodemon version 2.0.7 Latest version of nodemon have issue in windows (remy/nodemon#1889).
Any workarounds for the time being? It's not super critical but would be nice! |
If you're fine running a patched version, you can make the change in my previous comment. There's a chance you'll get stuck in an infinite loop but if you're function is simple enough maybe that's not a big enough deterrent? |
workaround for remy#1889
This does indeed log for a long time. Then asynchronously waiting for cleanup to be finished:
This indeed logs only the "start" and restarts in middle of cleanup. |
@lukepolo downgrade nodemon to 2.0.1 same for nodemon-webpack-plugin:
After this my above example correctly waits for the cleanup:
@remy do you have time for this? |
This is definitely what I encountered, the SIGUSR2 was sent twice in a short time, so no wait cleanup at all. |
turns out, maybe it's not only caused by nodemon. until this trick:
|
Running into this as well. With the Here's the code and output: function handleNodemonRestart() {
console.log("Nodemon requested cleanup");
cleanupServer()
.then(() => {
console.info("Finished nodemon cleanup");
process.kill(process.pid, "SIGUSR2");
})
.catch((err) => {
console.error("PANIC: failed to cleanup");
console.error(err);
process.exit(10);
});
setTimeout(() => {
process.off("SIGUSR2", handleNodemonRestart);
});
}
process.on("SIGUSR2", handleNodemonRestart);
|
@basicdays indeed, I suppose it should only off the handler when you are ready to exit:
|
Fwiw I do actually have the following code. Unfortunately it still causes the same issues on the latest version (3.0.1). Still stuck on version 2.0.1: // set nodemon restart handles
function handleNodemonRestart() {
logger.info("Nodemon requested cleanup");
stopServer()
.then(() => {
logger.info("Finished nodemon cleanup");
process.off("SIGUSR2", handleNodemonRestart);
process.kill(process.pid, "SIGUSR2");
})
.catch((err) => {
logger.error("PANIC: failed to cleanup");
logger.error(err);
process.exit(10);
});
}
process.on("SIGUSR2", handleNodemonRestart); |
@remy Looking through some of the other issues here, I saw your comment here. I just tested directly called nodemon instead of going through |
I had a same problem, so I have been stick on version 2.0.1 too |
For those of you sticking on v2.0.1 to avoid the issue, what version of node are you using? |
For me, currently on v20.8.0. Windows 11 |
@davemooreuws and 3.x behaves with the same bug as originally described? |
Yes, the node processes don't all get killed in version 3. At least on windows, not sure about other platforms. |
I'm writing to confirm that on version 3.1.0 this remains an issue. A hacky workaround is to call
|
currently using node 18 version |
Using v20.10.0 here. Just found this issue and downgraded from |
I'm experiencing the same thing using latest node and nodemon. I also tried downgrading versions but was unable to get the workarounds working in my docker environment. # Dockerfile
FROM node:20.10.0
RUN npm install nodemon@2.0.1 -g
COPY "start.sh" /app
ENTRYPOINT ["/usr/bin/env"]
CMD ["bash", "/app/start.sh"] # start.sh
npm install
nodemon -L index.ts // index.ts - shutdown code
process.on('SIGUSR2', async () => {
console.log('SIGUSR2 signal received');
await shutdown();
process.kill(process.pid, 'SIGUSR2');
}); |
I've finally dug into this and found that this line is the issue (introduced a while back) - but someone else recently opened an issue which was (effectively) the same issue (but I didn't put them together until today): 47dfb8b I the theoretical fix is to remove that single line, because a few lines later, the process sends an The reason why nodemon appears not to wait, is because the subprocess is recieving two It could be mitigated by using process.on('SIGUSR2', async () => {
console.log('SIGUSR2 signal received');
await shutdown();
process.kill(process.pid, 'SIGTERM');
}); This would trap the double So I've got two options:
My gut is to be wary of core code changes, and use documentation. But I'm happy to hear input. |
🎉 This issue has been resolved in version 3.1.4 🎉 The release is available on: Your semantic-release bot 📦🚀 |
nodemon -v
: 2.0.9node -v
: v16.1.0yarn 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 finishSteps to reproduce
create a file
watch.js
: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 manualkill -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.The text was updated successfully, but these errors were encountered: