uutils/coreutils · error · io::Error
kill-error-unsupported-signal
Error message
kill-error-unsupported-signal
What it means
On Windows, kill can only deliver a limited set of signals via native APIs. Requesting a signal the platform cannot send — notably SIGNAL_STOP (suspend), or any unimplemented signal number — returns io::ErrorKind::Unsupported with this translated message. It is a platform-capability limitation, not a bad PID or permission issue.
Source
Thrown at src/uu/kill/src/platform/windows.rs:22
// file that was distributed with this source code.
// spell-checker:ignore pids
//! Windows implementation of `kill`'s platform facade, built on the signal
//! emulation in [`uucore::process`]. PID 0 targets the Job object `kill` runs
//! in, the closest Windows analog of a process group. STOP (no process-suspend
//! API) and negative pids (no way to name another process's group) are
//! rejected.
use std::io;
use uucore::process::{enable_debug_privilege, send_signal_to_own_group, send_signal_to_pid};
use uucore::translate;
const SIGNAL_STOP: usize = 19;
fn unsupported(message: String) -> io::Error {
io::Error::new(io::ErrorKind::Unsupported, message)
}
pub(crate) fn send_signal(pid: i32, sig: usize) -> io::Result<()> {
if sig == SIGNAL_STOP {
return Err(unsupported(translate!("kill-error-unsupported-signal")));
}
match u32::try_from(pid) {
// Fails exactly for pid < 0.
Err(_) => Err(unsupported(translate!(
"kill-error-negative-pid-unsupported"
))),
Ok(pid) => {
// Group members need the same rights as a single target.
enable_debug_privilege();
if pid == 0 {
send_signal_to_own_group(sig)
} else {
send_signal_to_pid(pid, sig)View on GitHub (pinned to 325183372a)
Solutions
- Avoid STOP-type signals on Windows; terminate with a supported signal or use process suspension APIs explicitly
- Guard the call at runtime: check target OS (cfg!(windows)) and skip/replace suspend logic there
- On Windows use taskkill /PID <pid> for termination or a Windows-specific suspend mechanism (NtSuspendProcess) via a crate
- Refactor job control to be POSIX-only, gating it behind a unix-only code path
Example fix
// before
kill::send_signal(pid, 19)?; // SIGNAL_STOP
// after
if cfg!(windows) {
eprintln!("suspend not supported on windows");
} else {
kill::send_signal(pid, 19)?;
} Defensive patterns
Strategy: fallback
Validate before calling
// check signal support on the current platform before sending
const SIGNAL_STOP: usize = 19;
if cfg!(windows) && (sig == SIGNAL_STOP) {
eprintln!("{sig} unsupported on windows");
return;
} Type guard
fn signal_supported(sig: usize) -> bool {
!(cfg!(windows) && sig == 19) // SIGNAL_STOP
} Try / catch
match kill::send_signal(pid, sig) {
Err(e) if e.kind() == std::io::ErrorKind::Unsupported => {
eprintln!("signal {sig} unsupported here; using termination instead");
kill::send_signal(pid, default_terminate_signal)?;
}
other => other?,
} Prevention
- Gate job-control (STOP/TSTP) logic behind cfg(unix)
- Map signals to Windows equivalents (terminate) with explicit fallbacks
- Test cross-platform scripts for signal usage before deployment
When it happens
Trigger: Calling kill's send_signal(pid, sig) on Windows with sig == 19 (SIGNAL_STOP) or another signal Windows does not support (e.g., simulating SIGTSTP/SIGSTOP semantics).
Common situations: Scripts written for Unix that `kill -STOP`/`kill -TSTP` a process, job-control emulation in shells on Windows, cross-platform tooling that suspends/resumes worker processes.
Related errors
AI-assisted analysis of uutils/coreutils@325183372a (2026-08-31).
Data as JSON: /api/errors/7724ac181ffbc786.
Report an issue: GitHub.