Standardise shutdown signal guarding

This commit is contained in:
Cooldude2606 committed 2026-04-14 22:10:01 +01:00
1 parent e9653c13eb
commit e8cabb7196
6 files changed
+37 -75

No files matched your search

+3 -28
View File
@@ -18,7 +18,6 @@ import path from "path";
import fs from "node:fs/promises";
import crypto from "crypto";
import setBlocking from "set-blocking";
import yargs from "yargs";
import util from "util";
import winston from "winston";
@@ -446,33 +445,9 @@ async function startup() {
process.exit(1);
}
let secondSigint = false;
process.on("SIGINT", () => {
if (secondSigint) {
setBlocking(true);
logger.fatal("Caught second interrupt, terminating immediately");
process.exit(1);
}
secondSigint = true;
logger.info("Caught interrupt signal, shutting down");
controller.stop();
});
let secondSigterm = false;
process.on("SIGTERM", () => {
if (secondSigterm) {
setBlocking(true);
logger.fatal("Caught second termination, terminating immediately");
process.exit(1);
}
secondSigterm = true;
logger.info("Caught termination signal, shutting down");
controller.stop();
});
// Handle interrupts
process.on("SIGINT", lib.createShutdownGuard(logger, "interrupt", controller.stop.bind(controller)));
process.on("SIGTERM", lib.createShutdownGuard(logger, "termination", controller.stop.bind(controller)));
process.on("SIGHUP", () => {
logger.info("Terminal closed, shutting down");
controller.stop();
-2
View File
@@ -28,7 +28,6 @@
"finalhandler": "^1.3.1",
"jsonwebtoken": "catalog:",
"jszip": "catalog:",
"set-blocking": "catalog:",
"winston": "catalog:",
"winston-daily-rotate-file": "catalog:",
"ws": "catalog:",
@@ -43,7 +42,6 @@
"@types/finalhandler": "catalog:",
"@types/jsonwebtoken": "catalog:",
"@types/node": "catalog:",
"@types/set-blocking": "catalog:",
"@types/ws": "catalog:",
"@types/yargs": "^17.0.33",
"react": "catalog:",
+3 -16
View File
@@ -8,7 +8,6 @@ import fs from "node:fs/promises";
import yargs, { type Argv } from "yargs";
import path from "path";
import { version } from "./package.json";
import setBlocking from "set-blocking";
import { strict as assert } from "assert";
// Reduce startup time by lazy compiling schemas.
@@ -311,21 +310,9 @@ async function startControl() {
throw err;
}
let caughtSigInt = false;
process.on("SIGINT", () => {
if (caughtSigInt) {
logger.info("Caught second interrupt signal, forcing disconnect");
process.exit(1);
}
caughtSigInt = true;
logger.info("Caught interrupt signal, closing connection");
control.shutdown().catch(err => {
setBlocking(true);
logger.error(err.stack);
process.exit(1);
});
});
// Handle interrupts
process.on("SIGINT", lib.createShutdownGuard(logger, "interrupt", control.shutdown.bind(control)));
process.on("SIGTERM", lib.createShutdownGuard(logger, "termination", control.shutdown.bind(control)));
try {
const targetCommand = selectTargetCommand(args, rootCommands);
-2
View File
@@ -22,7 +22,6 @@
"dependencies": {
"@clusterio/lib": "workspace:*",
"as-table": "^1.0.55",
"set-blocking": "catalog:",
"winston": "catalog:",
"yargs": "^17.7.2"
},
@@ -31,7 +30,6 @@
},
"devDependencies": {
"@types/node": "catalog:",
"@types/set-blocking": "catalog:",
"@types/yargs": "^17.0.33",
"typescript": "catalog:"
}
+2 -27
View File
@@ -15,7 +15,6 @@
import fs from "node:fs/promises";
import path from "path";
import yargs from "yargs";
import setBlocking from "set-blocking";
import { version } from "./package.json";
import winston from "winston";
import "winston-daily-rotate-file";
@@ -239,32 +238,8 @@ async function startHost() {
);
// Handle interrupts
let secondSigint = false;
process.on("SIGINT", () => {
if (secondSigint) {
setBlocking(true);
logger.fatal("Caught second interrupt, terminating immediately");
process.exit(1);
}
secondSigint = true;
logger.info("Caught interrupt signal, shutting down");
host!.shutdown();
});
let secondSigterm = false;
process.on("SIGTERM", () => {
if (secondSigterm) {
setBlocking(true);
logger.fatal("Caught second termination, terminating immediately");
process.exit(1);
}
secondSigterm = true;
logger.info("Caught termination signal, shutting down");
host!.shutdown();
});
process.on("SIGINT", lib.createShutdownGuard(logger, "interrupt", host.shutdown.bind(host)));
process.on("SIGTERM", lib.createShutdownGuard(logger, "termination", host.shutdown.bind(host)));
process.on("SIGHUP", () => {
logger.info("Terminal closed, shutting down");
host!.shutdown();
+29
View File
@@ -3,6 +3,9 @@
* @module lib/helpers
*/
import type { Logger } from "./logging";
import setBlocking from "set-blocking";
/**
* Return a string describing the type of the value passed
*
@@ -51,6 +54,32 @@ export async function timeout<T>(promise: Promise<T>, limitMs: number, timeoutRe
}
}
/**
* Catch process signals, force exit on second signal
*/
export function createShutdownGuard(logger: Logger, signalName: string, callback: () => Promise<unknown>): () => void {
let called = false;
return () => {
if (called) {
setBlocking(true);
logger.fatal(`Caught second ${signalName}, terminating immediately`);
process.exit(1);
}
called = true;
logger.info(`Caught ${signalName}, shutting down`);
callback().catch(err => {
setBlocking(true);
logger.error(err.stack);
logger.fatal("Error during shutdown, terminating immediately");
process.exit(1);
});
};
}
/**
* Helper to serialise and merge waiting calls to an async callback.
*