Skip to content

Commit dfe0683

Browse files
committed
Auto merge of rust-lang#112594 - ChrisDenton:process=-kill, r=Amanieu
Return `Ok` on kill if process has already exited This will require an FCP from `@rust-lang/libs-api.` Fixes rust-lang#112423. See that issue for more details.
2 parents 99f7d36 + 9e5f61f commit dfe0683

File tree

5 files changed

+32
-14
lines changed

5 files changed

+32
-14
lines changed

library/std/src/process.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1904,8 +1904,8 @@ impl FromInner<imp::ExitCode> for ExitCode {
19041904
}
19051905

19061906
impl Child {
1907-
/// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
1908-
/// error is returned.
1907+
/// Forces the child process to exit. If the child has already exited, `Ok(())`
1908+
/// is returned.
19091909
///
19101910
/// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function.
19111911
///
@@ -1920,7 +1920,7 @@ impl Child {
19201920
///
19211921
/// let mut command = Command::new("yes");
19221922
/// if let Ok(mut child) = command.spawn() {
1923-
/// child.kill().expect("command wasn't running");
1923+
/// child.kill().expect("command couldn't be killed");
19241924
/// } else {
19251925
/// println!("yes command didn't start");
19261926
/// }

library/std/src/process/tests.rs

+15
Original file line numberDiff line numberDiff line change
@@ -582,3 +582,18 @@ fn run_canonical_bat_script() {
582582
assert!(output.status.success());
583583
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "Hello, fellow Rustaceans!");
584584
}
585+
586+
#[test]
587+
fn terminate_exited_process() {
588+
let mut cmd = if cfg!(target_os = "android") {
589+
let mut p = shell_cmd();
590+
p.args(&["-c", "true"]);
591+
p
592+
} else {
593+
known_command()
594+
};
595+
let mut p = cmd.stdout(Stdio::null()).spawn().unwrap();
596+
p.wait().unwrap();
597+
assert!(p.kill().is_ok());
598+
assert!(p.kill().is_ok());
599+
}

library/std/src/sys/unix/process/process_unix.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -762,12 +762,9 @@ impl Process {
762762
pub fn kill(&mut self) -> io::Result<()> {
763763
// If we've already waited on this process then the pid can be recycled
764764
// and used for another process, and we probably shouldn't be killing
765-
// random processes, so just return an error.
765+
// random processes, so return Ok because the process has exited already.
766766
if self.status.is_some() {
767-
Err(io::const_io_error!(
768-
ErrorKind::InvalidInput,
769-
"invalid argument: can't kill an exited process",
770-
))
767+
Ok(())
771768
} else {
772769
cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
773770
}

library/std/src/sys/unix/process/process_vxworks.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,9 @@ impl Process {
144144
pub fn kill(&mut self) -> io::Result<()> {
145145
// If we've already waited on this process then the pid can be recycled
146146
// and used for another process, and we probably shouldn't be killing
147-
// random processes, so just return an error.
147+
// random processes, so return Ok because the process has exited already.
148148
if self.status.is_some() {
149-
Err(io::const_io_error!(
150-
ErrorKind::InvalidInput,
151-
"invalid argument: can't kill an exited process",
152-
))
149+
Ok(())
153150
} else {
154151
cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
155152
}

library/std/src/sys/windows/process.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,16 @@ pub struct Process {
595595

596596
impl Process {
597597
pub fn kill(&mut self) -> io::Result<()> {
598-
cvt(unsafe { c::TerminateProcess(self.handle.as_raw_handle(), 1) })?;
598+
let result = unsafe { c::TerminateProcess(self.handle.as_raw_handle(), 1) };
599+
if result == c::FALSE {
600+
let error = unsafe { c::GetLastError() };
601+
// TerminateProcess returns ERROR_ACCESS_DENIED if the process has already been
602+
// terminated (by us, or for any other reason). So check if the process was actually
603+
// terminated, and if so, do not return an error.
604+
if error != c::ERROR_ACCESS_DENIED || self.try_wait().is_err() {
605+
return Err(crate::io::Error::from_raw_os_error(error as i32));
606+
}
607+
}
599608
Ok(())
600609
}
601610

0 commit comments

Comments
 (0)