From d5bd4ad5237508a2c882a7831c4235e3697c3daa Mon Sep 17 00:00:00 2001 From: dot Date: Thu, 8 Oct 2026 19:28:46 +0900 Subject: [PATCH 1/2] Ignore invalid descriptors in os.closerange Close raw descriptor numbers through the host CRT layer rather than constructing OwnedFd values for possibly closed descriptors. Preserve the half-open range, ignored close errors and Windows invalid-parameter handling. Assisted-by: Codex:model-version-unavailable --- crates/host_env/src/crt_fd.rs | 7 +++++++ crates/host_env/src/crt_fd_unsupported.rs | 2 ++ crates/vm/src/stdlib/os.rs | 6 +----- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/host_env/src/crt_fd.rs b/crates/host_env/src/crt_fd.rs index f06c5aad984..2390dc2aa83 100644 --- a/crates/host_env/src/crt_fd.rs +++ b/crates/host_env/src/crt_fd.rs @@ -348,6 +348,13 @@ pub fn close(fd: Owned) -> io::Result<()> { _close(fd.into_raw()) } +pub fn closerange(fd_low: Raw, fd_high: Raw) { + for fd in fd_low..fd_high { + // The range can contain closed descriptors, so it cannot use Owned. + let _ = _close(fd); + } +} + pub fn ftruncate(fd: Borrowed<'_>, len: Offset) -> io::Result<()> { let ret = unsafe { suppress_iph!(c::ftruncate(fd.as_raw(), len)) }; // On Windows, _chsize_s returns 0 on success, or a positive error code (errno value) on failure. diff --git a/crates/host_env/src/crt_fd_unsupported.rs b/crates/host_env/src/crt_fd_unsupported.rs index 7fb8a406e32..7b5336a9b98 100644 --- a/crates/host_env/src/crt_fd_unsupported.rs +++ b/crates/host_env/src/crt_fd_unsupported.rs @@ -153,6 +153,8 @@ pub fn close(_fd: Owned) -> io::Result<()> { Err(ebadf()) } +pub fn closerange(_fd_low: Raw, _fd_high: Raw) {} + pub fn ftruncate(_fd: Borrowed<'_>, _len: Offset) -> io::Result<()> { Err(ebadf()) } diff --git a/crates/vm/src/stdlib/os.rs b/crates/vm/src/stdlib/os.rs index 527643822b8..6f1dcca1556 100644 --- a/crates/vm/src/stdlib/os.rs +++ b/crates/vm/src/stdlib/os.rs @@ -272,11 +272,7 @@ pub(super) mod _os { #[pyfunction] fn closerange(fd_low: i32, fd_high: i32) { - for fileno in fd_low..fd_high { - if let Ok(fd) = unsafe { crt_fd::Owned::try_from_raw(fileno) } { - drop(fd); - } - } + crt_fd::closerange(fd_low, fd_high); } #[cfg(any(unix, windows, target_os = "wasi"))] From 1259e5c980b4fc689522e9539483e9e8d2022e53 Mon Sep 17 00:00:00 2001 From: dot Date: Thu, 8 Oct 2026 19:28:49 +0900 Subject: [PATCH 2/2] Use immediate exit for host process termination Python os._exit, failed child exec and fatal/watchdog exits must bypass C exit handlers. Call the host CRT _exit on Unix, Windows and WASI while retaining the existing non-host fallback. Normal interpreter termination is unchanged. Assisted-by: Codex:model-version-unavailable --- crates/host_env/src/os.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/host_env/src/os.rs b/crates/host_env/src/os.rs index 6eda6030c83..7d6879984bd 100644 --- a/crates/host_env/src/os.rs +++ b/crates/host_env/src/os.rs @@ -520,7 +520,11 @@ pub fn device_encoding(_fd: i32) -> Option { } pub fn exit(code: i32) -> ! { - std::process::exit(code) + // These callers require immediate termination without C exit handlers. + cfg_select! { + any(unix, windows, target_os = "wasi") => unsafe { libc::_exit(code) }, + _ => std::process::exit(code), + } } /// Wrapper around the C `abort()` call: terminates the process abnormally.