-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Description
Child::kill calls kill on Unix, and TerminateProcess on Windows.
If process is terminated, but handle is alive yet, kill is successful on Unix, but fails on Windows.
kill is successful on Unix because the process is zombie until waited (it fails after process waited, that's probably OK)
According to documentation of TerminateProcess
After a process has terminated, call to TerminateProcess with open handles to the process fails with ERROR_ACCESS_DENIED (5) error code
So if someone else (not us) terminated the process, kill would fail.
There are problems with this behavior:
- API is different between Unix and Windows
- API to reliably terminate the process is complicated
- call
kill - if
killfailed, need totry_wait. And iftry_waitis successful, ignore the error ofkill
- call
I could reproduce it. I don't have easy access to Windows machine to create completely isolated test case, but repro looks like this:
let mut command = std::process::Command::new("powershell");
command.args(["-c", "Start-Sleep -Seconds 10000"]);
let mut child = command.spawn().unwrap();
let pid = child.id().try_into().unwrap();
// Terminate by process id, NOT by our process handle. Like if some other process killed it.
// This function calls `OpenProcess(pid)` followed by `TerminateProcess`.
kill(pid).unwrap();
thread::sleep(Duration::from_secs(5));
child.kill().expect("Failed to kill child process");
This fails with:
Failed to kill child process: Os { code: 5, kind: PermissionDenied, message: "Access is denied." }
exactly as described in WinAPI docs.
I think proper kill implementation should look like this:
- if process has been waited already, fail explicitly, to be consistent with Unix
- call
TerminateProcess - if
TerminateProcessfailed, callGetExitCodeProcess - if
GetExitCodeProcessis successful and exit code is notSTILL_ACTIVE, considerkillsuccessful
This is how kill is implemented in our project:
Meta
rustc --version --verbose:
rustc 1.70.0-nightly