| author | |
| committer | |
| log | e8f3c4c4b12f59ac6fb1c2045a0635ce8f3d0dac |
| tree | 3e310c3db8301e11340b07800f8a1e8a2654feb9 |
| parent | 24b065a6a87da68bdefe228bb7e1d148e69edbd8 |
| parent | fb9376bd0499e2124616da1aeed7fe4e8bdd4f52 |
| signature |
return error.AlreadyTerminated from std.ChildProcess.kill when necessary3 files changed, 20 insertions(+), 5 deletions(-)
lib/std/child_process.zig+16-2| ... | @@ -221,7 +221,18 @@ pub const ChildProcess = struct { | ... | @@ -221,7 +221,18 @@ pub const ChildProcess = struct { |
| 221 | return term; | 221 | return term; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | try windows.TerminateProcess(self.id, exit_code); | 224 | windows.TerminateProcess(self.id, exit_code) catch |err| switch (err) { |
| 225 | error.PermissionDenied => { | ||
| 226 | // Usually when TerminateProcess triggers a ACCESS_DENIED error, it | ||
| 227 | // indicates that the process has already exited, but there may be | ||
| 228 | // some rare edge cases where our process handle no longer has the | ||
| 229 | // PROCESS_TERMINATE access right, so let's do another check to make | ||
| 230 | // sure the process is really no longer running: | ||
| 231 | windows.WaitForSingleObjectEx(self.handle, 0, false) catch return err; | ||
| 232 | return error.AlreadyTerminated; | ||
| 233 | }, | ||
| 234 | else => return err, | ||
| 235 | }; | ||
| 225 | try self.waitUnwrappedWindows(); | 236 | try self.waitUnwrappedWindows(); |
| 226 | return self.term.?; | 237 | return self.term.?; |
| 227 | } | 238 | } |
| ... | @@ -231,7 +242,10 @@ pub const ChildProcess = struct { | ... | @@ -231,7 +242,10 @@ pub const ChildProcess = struct { |
| 231 | self.cleanupStreams(); | 242 | self.cleanupStreams(); |
| 232 | return term; | 243 | return term; |
| 233 | } | 244 | } |
| 234 | try os.kill(self.id, os.SIG.TERM); | 245 | os.kill(self.id, os.SIG.TERM) catch |err| switch (err) { |
| 246 | error.ProcessNotFound => return error.AlreadyTerminated, | ||
| 247 | else => return err, | ||
| 248 | }; | ||
| 235 | try self.waitUnwrapped(); | 249 | try self.waitUnwrapped(); |
| 236 | return self.term.?; | 250 | return self.term.?; |
| 237 | } | 251 | } |
lib/std/os.zig+2-2| ... | @@ -639,14 +639,14 @@ pub fn raise(sig: u8) RaiseError!void { | ... | @@ -639,14 +639,14 @@ pub fn raise(sig: u8) RaiseError!void { |
| 639 | @compileError("std.os.raise unimplemented for this target"); | 639 | @compileError("std.os.raise unimplemented for this target"); |
| 640 | } | 640 | } |
| 641 | 641 | ||
| 642 | pub const KillError = error{PermissionDenied} || UnexpectedError; | 642 | pub const KillError = error{ ProcessNotFound, PermissionDenied } || UnexpectedError; |
| 643 | 643 | ||
| 644 | pub fn kill(pid: pid_t, sig: u8) KillError!void { | 644 | pub fn kill(pid: pid_t, sig: u8) KillError!void { |
| 645 | switch (errno(system.kill(pid, sig))) { | 645 | switch (errno(system.kill(pid, sig))) { |
| 646 | .SUCCESS => return, | 646 | .SUCCESS => return, |
| 647 | .INVAL => unreachable, // invalid signal | 647 | .INVAL => unreachable, // invalid signal |
| 648 | .PERM => return error.PermissionDenied, | 648 | .PERM => return error.PermissionDenied, |
| 649 | .SRCH => unreachable, // always a race condition | 649 | .SRCH => return error.ProcessNotFound, |
| 650 | else => |err| return unexpectedErrno(err), | 650 | else => |err| return unexpectedErrno(err), |
| 651 | } | 651 | } |
| 652 | } | 652 | } |
lib/std/os/windows.zig+2-1| ... | @@ -1593,11 +1593,12 @@ pub fn GetModuleFileNameW(hModule: ?HMODULE, buf_ptr: [*]u16, buf_len: DWORD) Ge | ... | @@ -1593,11 +1593,12 @@ pub fn GetModuleFileNameW(hModule: ?HMODULE, buf_ptr: [*]u16, buf_len: DWORD) Ge |
| 1593 | return buf_ptr[0..rc :0]; | 1593 | return buf_ptr[0..rc :0]; |
| 1594 | } | 1594 | } |
| 1595 | 1595 | ||
| 1596 | pub const TerminateProcessError = error{Unexpected}; | 1596 | pub const TerminateProcessError = error{ PermissionDenied, Unexpected }; |
| 1597 | 1597 | ||
| 1598 | pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError!void { | 1598 | pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError!void { |
| 1599 | if (kernel32.TerminateProcess(hProcess, uExitCode) == 0) { | 1599 | if (kernel32.TerminateProcess(hProcess, uExitCode) == 0) { |
| 1600 | switch (kernel32.GetLastError()) { | 1600 | switch (kernel32.GetLastError()) { |
| 1601 | Win32Error.ACCESS_DENIED => return error.PermissionDenied, | ||
| 1601 | else => |err| return unexpectedError(err), | 1602 | else => |err| return unexpectedError(err), |
| 1602 | } | 1603 | } |
| 1603 | } | 1604 | } |