deno/ext/node/ops/process.rs
Nathan Whitaker 9602e13d53
fix(process,node): roll our own process spawning on windows (#29609)
Fixes #16899.
Fixes https://github.com/denoland/deno/issues/23524.
Fixes https://github.com/denoland/deno/issues/23938.
Fixes https://github.com/denoland/deno/issues/27869.

Unblocks #5501.

This PR adds support for additional stdio pipes to windows, as well as
the detached option in `node:child_process`. I also ported over the
`kill` implementation for windows, which means we now can support
`kill(0)` as well as some other signals.

This means that playwright will now work on windows.

Now that we have a way to support detached processes on all platforms,
we can also easily add a `detached` option to `Deno.Command`, similar to
`child_process.spawn`.

---

The reason for moving away from `std::process::Command` is that the
standard library doesn't expose what we need to control the file
descriptor table of child processes on windows. The implementation here
is based off of parts of `std` and parts of `libuv`, and allows us to
support passing extra pipes in addition to detached processes on
windows.
2025-06-12 02:56:13 +00:00

40 lines
874 B
Rust

// Copyright 2018-2025 the Deno authors. MIT license.
use deno_core::op2;
use deno_core::OpState;
use deno_permissions::PermissionsContainer;
#[cfg(unix)]
fn kill(pid: i32, sig: i32) -> i32 {
// SAFETY: FFI call to libc
if unsafe { libc::kill(pid, sig) } < 0 {
std::io::Error::last_os_error().raw_os_error().unwrap()
} else {
0
}
}
#[cfg(not(unix))]
fn kill(pid: i32, _sig: i32) -> i32 {
match deno_subprocess_windows::process_kill(pid, _sig) {
Ok(_) => 0,
Err(e) => e.as_uv_error(),
}
}
#[op2(fast, stack_trace)]
pub fn op_node_process_kill(
state: &mut OpState,
#[smi] pid: i32,
#[smi] sig: i32,
) -> Result<i32, deno_permissions::PermissionCheckError> {
state
.borrow_mut::<PermissionsContainer>()
.check_run_all("process.kill")?;
Ok(kill(pid, sig))
}
#[op2(fast)]
pub fn op_process_abort() {
std::process::abort();
}