* Send SIGTERM (then SIGKILL) to `pid`, but ONLY if the running cmdline * contains `marker`. Prevents a stale state file from causing us to signal * an unrelated process that inherited the PID.
( pid: number, marker: string, verbose: boolean, )
| 330 | * an unrelated process that inherited the PID. |
| 331 | */ |
| 332 | async function killByPidWithIdentity( |
| 333 | pid: number, |
| 334 | marker: string, |
| 335 | verbose: boolean, |
| 336 | ): Promise<void> { |
| 337 | if (!pid || pid <= 0) return; |
| 338 | if (!isProcessAlive(pid)) return; |
| 339 | if (!verifyIdentity(pid, marker || CMDLINE_MARKER)) { |
| 340 | log( |
| 341 | verbose, |
| 342 | `pid ${pid} is alive but cmdline doesn't match marker '${marker || CMDLINE_MARKER}'; skipping signal (possible PID reuse)`, |
| 343 | ); |
| 344 | return; |
| 345 | } |
| 346 | try { |
| 347 | process.kill(pid, "SIGTERM"); |
| 348 | } catch { |
| 349 | // already gone |
| 350 | return; |
| 351 | } |
| 352 | // Give it a grace period; SIGKILL if still alive AND still ours. |
| 353 | const deadline = Date.now() + SIGTERM_GRACE_MS; |
| 354 | while (Date.now() < deadline) { |
| 355 | if (!isProcessAlive(pid)) return; |
| 356 | await delay(50); |
| 357 | } |
| 358 | if (isProcessAlive(pid) && verifyIdentity(pid, marker || CMDLINE_MARKER)) { |
| 359 | log(verbose, `pid ${pid} survived SIGTERM; SIGKILL`); |
| 360 | try { |
| 361 | process.kill(pid, "SIGKILL"); |
| 362 | } catch { |
| 363 | // raced with exit |
| 364 | } |
| 365 | } |
| 366 | } |
| 367 | |
| 368 | /** |
| 369 | * Public: $D daemon stop. Posts /shutdown if no active boards; otherwise |
no test coverage detected