-
-
Notifications
You must be signed in to change notification settings - Fork 2k
kill: implementation for Windows #13604
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
f054a72
358e372
d4fa484
9dcb1d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // This file is part of the uutils coreutils package. | ||
| // | ||
| // For the full copyright and license information, please view the LICENSE | ||
| // file that was distributed with this source code. | ||
|
|
||
| //! Platform-specific piece of `kill`: delivering one signal to one pid via | ||
| //! the [`send_signal`] facade, provided by both submodules with an identical | ||
| //! signature. The shared control flow stays in `kill.rs`. | ||
|
|
||
| #[cfg(unix)] | ||
| mod unix; | ||
| #[cfg(unix)] | ||
| pub(crate) use unix::*; | ||
|
|
||
| #[cfg(windows)] | ||
| mod windows; | ||
| #[cfg(windows)] | ||
| pub(crate) use windows::*; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| // This file is part of the uutils coreutils package. | ||
| // | ||
| // For the full copyright and license information, please view the LICENSE | ||
| // file that was distributed with this source code. | ||
|
|
||
| // spell-checker:ignore pids ESRCH | ||
|
|
||
| use std::cmp::Ordering; | ||
| use std::io; | ||
|
|
||
| use rustix::process::{ | ||
| Pid, Signal, kill_current_process_group, kill_process, kill_process_group, | ||
| test_kill_current_process_group, test_kill_process, test_kill_process_group, | ||
| }; | ||
|
|
||
| // rustix's `Signal` rejects libc-reserved realtime signals, so fall back to a | ||
| // raw `libc::kill` for any value its safe constructor doesn't recognize. | ||
| fn raw_kill(pid: i32, sig: usize) -> io::Result<()> { | ||
| let sig = i32::try_from(sig).map_err(|_| io::Error::from_raw_os_error(libc::EINVAL))?; | ||
| // SAFETY: plain FFI call; `kill` has no memory-safety preconditions. | ||
| if unsafe { libc::kill(pid as libc::pid_t, sig) } == 0 { | ||
| Ok(()) | ||
| } else { | ||
| Err(io::Error::last_os_error()) | ||
| } | ||
| } | ||
|
|
||
| /// Deliver `sig` to `pid` with kill(2) semantics: positive pids target one | ||
| /// process, 0 the current process group, negative pids the group `-pid`. | ||
| pub(crate) fn send_signal(pid: i32, sig: usize) -> io::Result<()> { | ||
| // Standard named signals use rustix's typed API; anything its safe | ||
| // constructor doesn't recognize (realtime/reserved) falls back to libc. | ||
| let named = (sig != 0) | ||
| .then(|| i32::try_from(sig).ok().and_then(Signal::from_named_raw)) | ||
| .flatten(); | ||
| match pid.cmp(&0) { | ||
| Ordering::Equal => match named { | ||
| _ if sig == 0 => test_kill_current_process_group().map_err(io::Error::from), | ||
| Some(s) => kill_current_process_group(s).map_err(io::Error::from), | ||
| None => raw_kill(0, sig), | ||
| }, | ||
| Ordering::Greater => { | ||
| let pid = Pid::from_raw(pid).expect("pid > 0 guaranteed by Ordering::Greater"); | ||
| match named { | ||
| _ if sig == 0 => test_kill_process(pid).map_err(io::Error::from), | ||
| Some(s) => kill_process(pid, s).map_err(io::Error::from), | ||
| None => raw_kill(pid.as_raw_nonzero().get(), sig), | ||
| } | ||
| } | ||
| Ordering::Less => { | ||
| // i32::MIN cannot be negated, so no such process group can exist. | ||
| let Some(abs_pid) = pid.checked_neg() else { | ||
| return Err(io::Error::from_raw_os_error(libc::ESRCH)); | ||
| }; | ||
| let pid = | ||
| Pid::from_raw(abs_pid).expect("abs_pid > 0 since pid < 0 and pid != i32::MIN"); | ||
| match named { | ||
| _ if sig == 0 => test_kill_process_group(pid).map_err(io::Error::from), | ||
| Some(s) => kill_process_group(pid, s).map_err(io::Error::from), | ||
| None => raw_kill(-pid.as_raw_nonzero().get(), sig), | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // This file is part of the uutils coreutils package. | ||
| // | ||
| // For the full copyright and license information, please view the LICENSE | ||
| // file that was distributed with this source code. | ||
|
|
||
| //! Windows implementation of `kill`'s platform facade, built on the signal | ||
| //! emulation in [`uucore::process`]. STOP (no process-suspend API) and | ||
| //! process groups (`pid <= 0`) have no Windows emulation and are rejected. | ||
|
|
||
| use std::io; | ||
|
|
||
| use uucore::process::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) { | ||
| Ok(pid) if pid != 0 => send_signal_to_pid(pid, sig), | ||
| _ => Err(unsupported(translate!( | ||
| "kill-error-process-groups-unsupported" | ||
| ))), | ||
|
Comment on lines
+27
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how do we get the handle? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no direct public Win32 or NT API for that. So, we got to get creative, and creative is unfortunately a bit involved. If you're using AI to code this, I assume it won't trouble you too much. Otherwise, let's consider this a TODO. The idea would be to iterate through all processes using NT APIs and filter down to the current process and get its Job ID. Then get all handles with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lets give it a shot |
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.