From 76225c6b9f9501f63c80ebb4b61b83bedce7e792 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Wed, 4 Mar 2026 00:48:38 +0000 Subject: [PATCH] fix(lifecycle): use process group kill (-pid) in handleExit safety net With detached:true children, the synchronous exit handler must kill the entire process group, not just the direct PID. --- package.json | 2 +- ts/smartexit.classes.lifecycle.ts | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 66453d7..72e6d63 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@push.rocks/smartexit", - "version": "2.0.1", + "version": "2.0.2", "private": false, "description": "A library for managing graceful shutdowns of Node.js processes by handling cleanup operations, including terminating child processes.", "main": "dist_ts/index.js", diff --git a/ts/smartexit.classes.lifecycle.ts b/ts/smartexit.classes.lifecycle.ts index d7c0eb9..ed3fc76 100644 --- a/ts/smartexit.classes.lifecycle.ts +++ b/ts/smartexit.classes.lifecycle.ts @@ -187,18 +187,25 @@ export class ProcessLifecycle { }); } - /** Synchronous last-resort: SIGKILL any remaining tracked PIDs. */ + /** Synchronous last-resort: SIGKILL any remaining tracked process groups. */ private handleExit(): void { const instances = ProcessLifecycle.getInstances(); let killed = 0; for (const instance of instances) { for (const pid of instance.trackedPids) { + // Kill entire process group (negative PID) for detached children try { - process.kill(pid, 'SIGKILL'); + process.kill(-pid, 'SIGKILL'); killed++; } catch { - // Process already dead + // Process group may not exist, try single PID + try { + process.kill(pid, 'SIGKILL'); + killed++; + } catch { + // Process already dead + } } } }