about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/process.rs6
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs7
-rw-r--r--library/std/src/sys/unix/process/process_vxworks.rs7
-rw-r--r--library/std/src/sys/windows/process.rs11
4 files changed, 17 insertions, 14 deletions
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 9da74a5ddb5..8f3201b0091 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -1904,8 +1904,8 @@ impl FromInner<imp::ExitCode> for ExitCode {
 }
 
 impl Child {
-    /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
-    /// error is returned.
+    /// Forces the child process to exit. If the child has already exited, `Ok(())`
+    /// is returned.
     ///
     /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function.
     ///
@@ -1920,7 +1920,7 @@ impl Child {
     ///
     /// let mut command = Command::new("yes");
     /// if let Ok(mut child) = command.spawn() {
-    ///     child.kill().expect("command wasn't running");
+    ///     child.kill().expect("command couldn't be killed");
     /// } else {
     ///     println!("yes command didn't start");
     /// }
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 3721988b405..d527e1d7ead 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -719,12 +719,9 @@ impl Process {
     pub fn kill(&mut self) -> io::Result<()> {
         // If we've already waited on this process then the pid can be recycled
         // and used for another process, and we probably shouldn't be killing
-        // random processes, so just return an error.
+        // random processes, so return Ok because the process has exited already.
         if self.status.is_some() {
-            Err(io::const_io_error!(
-                ErrorKind::InvalidInput,
-                "invalid argument: can't kill an exited process",
-            ))
+            Ok(())
         } else {
             cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
         }
diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs
index c40e7ada03c..f70d3cb396b 100644
--- a/library/std/src/sys/unix/process/process_vxworks.rs
+++ b/library/std/src/sys/unix/process/process_vxworks.rs
@@ -144,12 +144,9 @@ impl Process {
     pub fn kill(&mut self) -> io::Result<()> {
         // If we've already waited on this process then the pid can be recycled
         // and used for another process, and we probably shouldn't be killing
-        // random processes, so just return an error.
+        // random processes, so return Ok because the process has exited already.
         if self.status.is_some() {
-            Err(io::const_io_error!(
-                ErrorKind::InvalidInput,
-                "invalid argument: can't kill an exited process",
-            ))
+            Ok(())
         } else {
             cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
         }
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index a573a05c39c..e3493cbb850 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -595,7 +595,16 @@ pub struct Process {
 
 impl Process {
     pub fn kill(&mut self) -> io::Result<()> {
-        cvt(unsafe { c::TerminateProcess(self.handle.as_raw_handle(), 1) })?;
+        let result = unsafe { c::TerminateProcess(self.handle.as_raw_handle(), 1) };
+        if result == c::FALSE {
+            let error = unsafe { c::GetLastError() };
+            // TerminateProcess returns ERROR_ACCESS_DENIED if the process has already been
+            // terminated (by us, or for any other reason). So check if the process was actually
+            // terminated, and if so, do not return an error.
+            if error != c::ERROR_ACCESS_DENIED || self.try_wait().is_err() {
+                return Err(crate::io::Error::from_raw_os_error(error as i32));
+            }
+        }
         Ok(())
     }