deno
4e53408c - fix(ext/process): treat Windows kill on exited process as NotFound (#34889)

Commit
56 days ago
fix(ext/process): treat Windows kill on exited process as NotFound (#34889) ## Problem On Windows, `kill("SIGTERM")` randomly threw `PermissionError`, depending on the timing/availability of resources. When this happened via an `AbortSignal` it produced an uncaught error the user had no way to handle (the Windows node-compat report would come back randomly empty because of it). ## Root cause On Windows, `kill()` opens the target with `OpenProcess(PROCESS_TERMINATE, ...)` (`ext/process/lib.rs`). If the child has already exited — or its pid was reused — `OpenProcess` can fail with `ERROR_ACCESS_DENIED (5)`, which was mapped via `Error::from_raw_os_error(5)` → `ErrorKind::PermissionDenied` → JS `PermissionError`. That is the "randomly throws" race. Unix returns `ESRCH` → `NotFound` for the same situation. ## Fix - `ext/process/lib.rs`: when `OpenProcess(PROCESS_TERMINATE, ...)` fails with `ERROR_ACCESS_DENIED` **and** the process is no longer alive, map it to `NotFound` (mirroring Unix `ESRCH`) instead of `PermissionError`. A process that is genuinely still alive but that the caller lacks rights to terminate still yields `PermissionError`. Liveness is checked with a small `process_is_alive()` helper (`OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION)` + `GetExitCodeProcess` == `STILL_ACTIVE`), which also de-duplicates the existing signal-0 health-check branch. - `ext/node/polyfills/internal/child_process.ts`: the `kill()` "already closed" handling now treats `Deno.errors.NotFound` as benign (alongside `TypeError` and `PermissionDenied`), so a dead-process kill returns `false` instead of throwing — on both platforms. The abort-signal *symptom* was already masked by try/catch in the `Deno.Command` abort handlers (#27112, #34069); this change addresses the underlying root cause so an explicit `.kill()` during the exit window no longer surfaces a misleading `PermissionError`. ## Tests Added two `tests/unit_node/child_process_test.ts` cases: - an `AbortSignal` aborts the child and emits an `AbortError` (Node semantics) without an uncaught error; - `kill()` on an already-exited process returns `false` and does not throw. Verified the Windows-only Rust compiles & is clippy-clean via `cargo {check,clippy} -p deno_process --target x86_64-pc-windows-msvc`. Closes #28882 Closes denoland/divybot#486 Co-authored-by: divybot <divybot@users.noreply.github.com> Co-authored-by: Divy Srivastava <me@littledivy.com>
Author
Parents
Loading