fix(smartexit): use native OS methods to kill process trees; remove tree-kill dependency

This commit is contained in:
2026-03-04 17:55:47 +00:00
parent 76225c6b9f
commit 28a09f63b2
6 changed files with 40 additions and 24 deletions

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@push.rocks/smartexit',
version: '1.1.1',
version: '2.0.3',
description: 'A library for managing graceful shutdowns of Node.js processes by handling cleanup operations, including terminating child processes.'
}

View File

@@ -56,21 +56,31 @@ export type TProcessSignal =
export class SmartExit {
/** Kill an entire process tree by PID. */
public static async killTreeByPid(pidArg: number, signalArg: TProcessSignal = 'SIGKILL') {
const done = plugins.smartpromise.defer();
plugins.treeKill.default(pidArg, signalArg, (err) => {
if (err) {
done.reject(err);
} else {
done.resolve();
if (process.platform === 'win32') {
// Windows: use native taskkill for tree kill
try {
plugins.childProcess.execSync(`taskkill /T /F /PID ${pidArg}`, { stdio: 'ignore' });
} catch {
// Process already dead
}
});
await done.promise;
} else {
// POSIX: kill the entire process group via negative PID.
// Works even for grandchildren reparented to PID 1.
try {
process.kill(-pidArg, signalArg);
} catch (err: any) {
if (err.code !== 'ESRCH') {
// ESRCH = no such process/group, already dead — that's fine
throw err;
}
}
}
}
// Instance state
public processesToEnd = new plugins.lik.ObjectMap<plugins.childProcess.ChildProcess>();
public cleanupFunctions = new plugins.lik.ObjectMap<() => Promise<any>>();
/** PIDs tracked independently — survives removeProcess() so shutdown can still kill the tree. */
/** PIDs tracked independently for tree-killing during shutdown. */
public trackedPids = new Set<number>();
private options: ISmartExitOptions;
@@ -108,6 +118,9 @@ export class SmartExit {
/** Unregister a child process. */
public removeProcess(childProcessArg: plugins.childProcess.ChildProcess) {
this.processesToEnd.remove(childProcessArg);
if (childProcessArg.pid) {
this.trackedPids.delete(childProcessArg.pid);
}
}
/**

View File

@@ -9,9 +9,3 @@ import * as smartpromise from '@push.rocks/smartpromise';
export { lik, smartpromise };
// third party scope
import * as treeKill from 'tree-kill';
export {
treeKill
}