1 | import { Disposable } from '@stryker-mutator/api/plugin';
|
2 |
|
3 | import { coreTokens } from './di/index.js';
|
4 |
|
5 | export type ExitHandler = () => void;
|
6 |
|
7 | const signals = Object.freeze(['SIGABRT', 'SIGINT', 'SIGHUP', 'SIGTERM']);
|
8 | export class UnexpectedExitHandler implements Disposable {
|
9 | private readonly unexpectedExitHandlers: ExitHandler[] = [];
|
10 |
|
11 | public static readonly inject = [coreTokens.process] as const;
|
12 | constructor(private readonly process: Pick<NodeJS.Process, 'exit' | 'off' | 'on'>) {
|
13 | process.on('exit', this.handleExit);
|
14 | signals.forEach((signal) => process.on(signal, this.processSignal));
|
15 | }
|
16 | private readonly processSignal = (_signal: string, signalNumber: number) => {
|
17 |
|
18 |
|
19 | this.process.exit(128 + signalNumber);
|
20 | };
|
21 |
|
22 | private readonly handleExit = () => {
|
23 | this.unexpectedExitHandlers.forEach((handler) => handler());
|
24 | };
|
25 |
|
26 | public registerHandler(handler: ExitHandler): void {
|
27 | this.unexpectedExitHandlers.push(handler);
|
28 | }
|
29 |
|
30 | public dispose(): void {
|
31 | this.process.off('exit', this.handleExit);
|
32 | signals.forEach((signal) => this.process.off(signal, this.processSignal));
|
33 | }
|
34 | }
|