-
-
Notifications
You must be signed in to change notification settings - Fork 7.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
Fix process not ending correctly with shutdown hooks #14433
Conversation
@@ -368,7 +368,7 @@ export class NestApplicationContext< | |||
await this.dispose(); | |||
await this.callShutdownHook(signal); | |||
signals.forEach(sig => process.removeListener(sig, cleanup)); | |||
process.kill(process.pid, signal); | |||
process.exit(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I'm following. process.exit
(force exit) shouldn't be necessary. We're also overriding the signal (the reason to kill the process) here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
console.log("Hello CodeSandbox");
process.on("SIGTERM", () => {
console.log("SIGTERM received");
process.kill(process.pid, "SIGTERM");
});
process.on("exit", () => {
console.log("about to exit");
});
setTimeout(() => {
console.log("killing");
process.kill(process.pid, "SIGTERM");
}, 1000);
There "about to exit" is called. I don't understand why my unit test is failing without changing to process.exit(0).
I understand you'd want to wait for node to start the shutdown process - maybe the problem is coming from nestjs/cli / commander not waiting or not emitting the exit event on the child process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't work even if you run node dist/main
(no NestJS CLI involved)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thomaschaaf@MacBookPro sigterm % cat index.js
console.log("Hello CodeSandbox");
process.on("SIGTERM", () => {
console.log("SIGTERM received");
process.kill(process.pid, "SIGTERM");
});
process.on("exit", () => {
console.log("about to exit");
});
setTimeout(() => {
console.log("killing");
process.kill(process.pid, "SIGTERM");
}, 1000);
thomaschaaf@MacBookPro sigterm % node index.js
Hello CodeSandbox
killing
SIGTERM received
about to exit
thomaschaaf@MacBookPro sigterm % node -v
v18.18.2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still cannot reproduce your issue with the following code:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableShutdownHooks();
await app.listen(3000);
console.log(`Application is running on: ${await app.getUrl()}`);
process.on('SIGTERM', async () => {
await app.close();
console.log('SIGTERM received');
process.kill(process.pid, 'SIGTERM');
});
process.on('exit', () => {
console.log('about to exit');
});
setTimeout(() => {
console.log('killing');
process.kill(process.pid, 'SIGTERM');
}, 1000);
}
bootstrap();
With node dist/main
:
Application is running on: http://[::1]:3000
killing
SIGTERM received
about to exit
With nest start
Same with nest start --watch
(npm run start:dev)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know you just released your own json logger - so it might not be your issue.
In the end I only care the exit listener because pino is using https://www.npmjs.com/package/on-exit-leak-free to flush the logs in the shutdown scenario to clear the buffers of the logger. Pino is using a worker thread to do the writing to stdout to be more performant. One alternative solution I came up with was calling logger.flush() before the kill.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will try out my example again and upload it to github - maybe it's something that got changed with v11
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you accidentally found the issue 🤯
I created https://github.com/thomaschaaf/debug-nest-js-on-exit you can start it with either
SIGTERM=1 ./node_modules/.bin/nest start
or
SIGTERM=0 ./node_modules/.bin/nest start
This toggles: https://github.com/thomaschaaf/debug-nest-js-on-exit/blob/main/src/main.ts#L30-L33
I have also added an extra console log in pino: https://github.com/thomaschaaf/debug-nest-js-on-exit/blob/main/node_modules/pino/lib/transport.js#L62
The interesting bit is if you have no handler for sigterm the process.on('exit') is not called. I don't understand why.. With the change in the pr it is "fixed" but I understand it seems to be more of a workaround. I guess we will just add a handler
process.on('SIGTERM', () => {
// fix 'exit' event not triggered without this.
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can replicate the exact same behavior using plain Node.js (without the Nest framework/CLI), so I'm not sure if there's anything we need to change on our end.
Setting a process.on('SIGTERM', () => {
// fix 'exit' event not triggered without this.
}); seems to fix the issue that process.on('exit') does not get triggered. |
fixes #14432
https://codesandbox.io/p/sandbox/sad-noyce-6zrk6c
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: #14432
What is the new behavior?
https://nodejs.org/api/process.html#event-exit is now called when shutdown is complete
Does this PR introduce a breaking change?