* Windows has no POSIX process groups: ChildProcess#kill reaches only the * direct child (e.g. the uvx wrapper), leaving grandchildren — the actual * python agent-server holding its port — running. `taskkill /t` walks the * child tree instead. Windows also has no graceful tree signal (taskkill *
(proc, signal)
| 111 | * a failure to spawn taskkill itself falls back to the direct kill. |
| 112 | */ |
| 113 | function killWindowsProcessTree(proc, signal) { |
| 114 | const result = spawnSync( |
| 115 | "taskkill", |
| 116 | ["/pid", String(proc.pid), "/t", "/f"], |
| 117 | // windowsHide avoids a console window flash when invoked from the |
| 118 | // packaged (GUI) Electron process. |
| 119 | { stdio: "ignore", windowsHide: true }, |
| 120 | ); |
| 121 | if (result.error) { |
| 122 | proc.kill(signal); |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | export function createShutdownHookRegistry(onError) { |
| 127 | const hooks = new Set(); |