uutils/coreutils · info · io::Error
error-no-such-process
Error message
error-no-such-process
What it means
On Windows, `no_such_process` constructs an `io::Error` with `ErrorKind::NotFound` carrying the localized "error-no-such-process" message. `probe_pid` opens the process with PROCESS_SYNCHRONIZE only; if the open fails with ERROR_ACCESS_DENIED (a real denial after a failed TerminateProcess) versus the process already having exited, this error signals the process does not exist.
Source
Thrown at src/uucore/src/lib/features/process/windows.rs:481
Disposition::Probe => match sys::wait_for_one(child.as_handle(), 0)? {
sys::WaitOutcome::TimedOut => Ok(()),
// The process has exited: the POSIX analog is ESRCH.
sys::WaitOutcome::Object(_) => Err(io::ErrorKind::NotFound.into()),
},
Disposition::Ignore => Ok(()),
Disposition::Interrupt | Disposition::Terminate => {
terminate_with_signal(child.as_handle(), signal)
}
}
}
const PROBE_ACCESS: u32 = PROCESS_SYNCHRONIZE;
// SYNCHRONIZE tells "already exited" apart from a real denial after a failed
// TerminateProcess (both report ERROR_ACCESS_DENIED).
const TERMINATE_ACCESS: u32 = PROCESS_TERMINATE | PROCESS_SYNCHRONIZE;
fn no_such_process() -> io::Error {
io::Error::new(io::ErrorKind::NotFound, translate!("error-no-such-process"))
}
/// A process handle becomes signaled when the process exits.
fn has_exited(handle: BorrowedHandle) -> io::Result<bool> {
Ok(matches!(
sys::wait_for_one(handle, 0)?,
sys::WaitOutcome::Object(_)
))
}
/// Request `SeDebugPrivilege` once per process; with it, opening a process
/// bypasses the target's security descriptor.
///
/// Silent and best-effort: only an elevated administrator's token holds the
/// privilege, and tokens without it are left untouched.
pub fn enable_debug_privilege() {
static REQUESTED: OnceLock<()> = OnceLock::new();
REQUESTED.get_or_init(|| {View on GitHub (pinned to 325183372a)
Solutions
- Check the process still exists before signaling, and treat NotFound as success for kill semantics
- Refresh the PID from the source that spawned it
- Ignore this error in fire-and-forget termination logic
Example fix
// before
kill(pid).expect("kill failed");
// after
if let Err(e) = kill(pid) {
if e.kind() != io::ErrorKind::NotFound {
return Err(e);
} // already exited: fine
} Defensive patterns
Strategy: try-catch
Validate before calling
// Windows: probe first
fn pid_exists(pid: u32) -> bool {
// probe_pid returns Err(NotFound) if the process has exited
probe::probe_pid(pid).is_ok()
} Type guard
fn is_no_such_process(e: &std::io::Error) -> bool {
e.kind() == std::io::ErrorKind::NotFound
&& e.to_string().contains("no such process")
} Try / catch
if let Err(e) = kill(pid) {
if !is_no_such_process(&e) { return Err(e); }
// already exited: treat as success
} Prevention
- Treat NotFound as success in idempotent kill logic
- Avoid caching PIDs across sessions
- Re-read PID files right before signaling
When it happens
Trigger: Calling `probe_pid` (and by extension kill/terminate paths) with a PID whose process has already exited, or a PID that never existed on the system.
Common situations: Killing a process that already terminated (race), stale PIDs from a previous session, PID reuse assumptions in scripts.
Related errors
AI-assisted analysis of uutils/coreutils@325183372a (2026-08-31).
Data as JSON: /api/errors/8dd4467172931821.
Report an issue: GitHub.