Skip to content

Commit

Permalink
feat: always try a graceful shutdown on first SIGINT
Browse files Browse the repository at this point in the history
If the process is running from a terminal, display a message to the user
telling that they can press CTRL+C again to force an immediate shutdown.

Closes: adonisjs-community/create-adonis-ts-app#5
  • Loading branch information
targos committed Feb 18, 2021
1 parent 3787353 commit 3598a60
Showing 1 changed file with 24 additions and 13 deletions.
37 changes: 24 additions & 13 deletions src/Ignitor/SignalsListener/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,36 @@ import { ApplicationContract } from '@ioc:Adonis/Core/Application'

/**
* Exposes the API to invoke a callback when `SIGTERM` or
* `SIGINT (pm2 only)` signals are received.
* `SIGINT` signals are received.
*/
export class SignalsListener {
protected onCloseCallback?: () => Promise<void>

private isKilling = false

/**
* Invoke callback and exit process
*/
private kill = async function () {
try {
await this.onCloseCallback()
private kill = async () => {
if (!this.isKilling) {
// First attempt. Try to kill the process gracefully.
this.isKilling = true
if (process.stderr.isTTY) {
// If the process is running in a terminal, display a message to the user.
console.error('Gracefully shutting down the process... Press CTRL+C to force it')
}
try {
await this.onCloseCallback()
process.exit(0)
} catch (error) {
// TODO: log error?
process.exit(1)
}
} else {
// Second attempt. Force process termination.
process.exit(0)
} catch (error) {
process.exit(1)
}
}.bind(this)
}

constructor(private application: ApplicationContract) {}

Expand All @@ -36,16 +50,13 @@ export class SignalsListener {
*/
public listen(callback: () => Promise<void>) {
this.onCloseCallback = callback
if (process.env.pm_id) {
process.once('SIGINT', this.kill)
}

process.once('SIGTERM', this.kill)
process.on('SIGINT', this.kill)
process.on('SIGTERM', this.kill)

/**
* Cleanup on uncaught exceptions.
*/
process.once('uncaughtException', (error) => {
process.on('uncaughtException', (error) => {
if (this.application.environment === 'repl') {
this.application.logger.fatal(error, '"uncaughtException" detected')
return
Expand Down

0 comments on commit 3598a60

Please sign in to comment.