mirror of
https://github.com/ziglang/zig.git
synced 2025-12-10 16:23:07 +00:00
Merge pull request #13610 from bcrist/child_process_already_terminated
return error.AlreadyTerminated from std.ChildProcess.kill when necessary
This commit is contained in:
commit
e8f3c4c4b1
@ -221,7 +221,18 @@ pub const ChildProcess = struct {
|
|||||||
return term;
|
return term;
|
||||||
}
|
}
|
||||||
|
|
||||||
try windows.TerminateProcess(self.id, exit_code);
|
windows.TerminateProcess(self.id, exit_code) catch |err| switch (err) {
|
||||||
|
error.PermissionDenied => {
|
||||||
|
// Usually when TerminateProcess triggers a ACCESS_DENIED error, it
|
||||||
|
// indicates that the process has already exited, but there may be
|
||||||
|
// some rare edge cases where our process handle no longer has the
|
||||||
|
// PROCESS_TERMINATE access right, so let's do another check to make
|
||||||
|
// sure the process is really no longer running:
|
||||||
|
windows.WaitForSingleObjectEx(self.handle, 0, false) catch return err;
|
||||||
|
return error.AlreadyTerminated;
|
||||||
|
},
|
||||||
|
else => return err,
|
||||||
|
};
|
||||||
try self.waitUnwrappedWindows();
|
try self.waitUnwrappedWindows();
|
||||||
return self.term.?;
|
return self.term.?;
|
||||||
}
|
}
|
||||||
@ -231,7 +242,10 @@ pub const ChildProcess = struct {
|
|||||||
self.cleanupStreams();
|
self.cleanupStreams();
|
||||||
return term;
|
return term;
|
||||||
}
|
}
|
||||||
try os.kill(self.id, os.SIG.TERM);
|
os.kill(self.id, os.SIG.TERM) catch |err| switch (err) {
|
||||||
|
error.ProcessNotFound => return error.AlreadyTerminated,
|
||||||
|
else => return err,
|
||||||
|
};
|
||||||
try self.waitUnwrapped();
|
try self.waitUnwrapped();
|
||||||
return self.term.?;
|
return self.term.?;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -639,14 +639,14 @@ pub fn raise(sig: u8) RaiseError!void {
|
|||||||
@compileError("std.os.raise unimplemented for this target");
|
@compileError("std.os.raise unimplemented for this target");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const KillError = error{PermissionDenied} || UnexpectedError;
|
pub const KillError = error{ ProcessNotFound, PermissionDenied } || UnexpectedError;
|
||||||
|
|
||||||
pub fn kill(pid: pid_t, sig: u8) KillError!void {
|
pub fn kill(pid: pid_t, sig: u8) KillError!void {
|
||||||
switch (errno(system.kill(pid, sig))) {
|
switch (errno(system.kill(pid, sig))) {
|
||||||
.SUCCESS => return,
|
.SUCCESS => return,
|
||||||
.INVAL => unreachable, // invalid signal
|
.INVAL => unreachable, // invalid signal
|
||||||
.PERM => return error.PermissionDenied,
|
.PERM => return error.PermissionDenied,
|
||||||
.SRCH => unreachable, // always a race condition
|
.SRCH => return error.ProcessNotFound,
|
||||||
else => |err| return unexpectedErrno(err),
|
else => |err| return unexpectedErrno(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1593,11 +1593,12 @@ pub fn GetModuleFileNameW(hModule: ?HMODULE, buf_ptr: [*]u16, buf_len: DWORD) Ge
|
|||||||
return buf_ptr[0..rc :0];
|
return buf_ptr[0..rc :0];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const TerminateProcessError = error{Unexpected};
|
pub const TerminateProcessError = error{ PermissionDenied, Unexpected };
|
||||||
|
|
||||||
pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError!void {
|
pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError!void {
|
||||||
if (kernel32.TerminateProcess(hProcess, uExitCode) == 0) {
|
if (kernel32.TerminateProcess(hProcess, uExitCode) == 0) {
|
||||||
switch (kernel32.GetLastError()) {
|
switch (kernel32.GetLastError()) {
|
||||||
|
Win32Error.ACCESS_DENIED => return error.PermissionDenied,
|
||||||
else => |err| return unexpectedError(err),
|
else => |err| return unexpectedError(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user