| ... | @@ -1188,7 +1188,6 @@ pub fn init( | ... | @@ -1188,7 +1188,6 @@ pub fn init( |
| 1188 | .argv0 = options.argv0, | 1188 | .argv0 = options.argv0, |
| 1189 | .worker_threads = .init(null), | 1189 | .worker_threads = .init(null), |
| 1190 | .environ = .{ .process_environ = options.environ }, | 1190 | .environ = .{ .process_environ = options.environ }, |
| 1191 | .robust_cancel = options.robust_cancel, | | |
| 1192 | }; | 1191 | }; |
| 1193 | | 1192 | |
| 1194 | if (posix.Sigaction != void) { | 1193 | if (posix.Sigaction != void) { |
| ... | @@ -13050,9 +13049,10 @@ fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) proce | ... | @@ -13050,9 +13049,10 @@ fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) proce |
| 13050 | fn childWait(userdata: ?*anyopaque, child: *process.Child) process.Child.WaitError!process.Child.Term { | 13049 | fn childWait(userdata: ?*anyopaque, child: *process.Child) process.Child.WaitError!process.Child.Term { |
| 13051 | if (native_os == .wasi) unreachable; | 13050 | if (native_os == .wasi) unreachable; |
| 13052 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 13051 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| | 13052 | _ = t; |
| 13053 | switch (native_os) { | 13053 | switch (native_os) { |
| 13054 | .windows => return childWaitWindows(t, child), | 13054 | .windows => return childWaitWindows(child), |
| 13055 | else => return childWaitPosix(Thread.getCurrent(t), child), | 13055 | else => return childWaitPosix(child), |
| 13056 | } | 13056 | } |
| 13057 | } | 13057 | } |
| 13058 | | 13058 | |
| ... | @@ -13062,7 +13062,8 @@ fn childKill(userdata: ?*anyopaque, child: *process.Child) void { | ... | @@ -13062,7 +13062,8 @@ fn childKill(userdata: ?*anyopaque, child: *process.Child) void { |
| 13062 | if (is_windows) { | 13062 | if (is_windows) { |
| 13063 | childKillWindows(t, child, 1) catch childCleanupWindows(child); | 13063 | childKillWindows(t, child, 1) catch childCleanupWindows(child); |
| 13064 | } else { | 13064 | } else { |
| 13065 | childKillPosix(Thread.getCurrent(t), child) catch childCleanupPosix(child); | 13065 | childKillPosix(child) catch {}; |
| | 13066 | childCleanupPosix(child); |
| 13066 | } | 13067 | } |
| 13067 | } | 13068 | } |
| 13068 | | 13069 | |
| ... | @@ -13087,21 +13088,24 @@ fn childKillWindows(t: *Threaded, child: *process.Child, exit_code: windows.UINT | ... | @@ -13087,21 +13088,24 @@ fn childKillWindows(t: *Threaded, child: *process.Child, exit_code: windows.UINT |
| 13087 | childCleanupWindows(child); | 13088 | childCleanupWindows(child); |
| 13088 | } | 13089 | } |
| 13089 | | 13090 | |
| 13090 | fn childWaitWindows(t: *Threaded, child: *process.Child) process.Child.WaitError!process.Child.Term { | 13091 | fn childWaitWindows(child: *process.Child) process.Child.WaitError!process.Child.Term { |
| 13091 | const current_thread = Thread.getCurrent(t); | | |
| 13092 | const handle = child.id.?; | 13092 | const handle = child.id.?; |
| 13093 | | 13093 | |
| 13094 | while (true) { | 13094 | var syscall: Syscall = try .start(); |
| 13095 | try current_thread.checkCancel(); | 13095 | while (true) switch (windows.kernel32.WaitForSingleObjectEx(handle, windows.INFINITE, windows.FALSE)) { |
| 13096 | switch (windows.kernel32.WaitForSingleObjectEx(handle, windows.INFINITE, windows.FALSE)) { | 13096 | windows.WAIT_OBJECT_0 => break syscall.finish(), |
| 13097 | windows.WAIT_OBJECT_0 => break, | 13097 | windows.WAIT_ABANDONED, windows.WAIT_TIMEOUT => { |
| 13098 | windows.WAIT_ABANDONED, windows.WAIT_TIMEOUT => continue, | 13098 | try syscall.checkCancel(); |
| 13099 | windows.WAIT_FAILED => switch (windows.GetLastError()) { | 13099 | continue; |
| | 13100 | }, |
| | 13101 | windows.WAIT_FAILED => { |
| | 13102 | syscall.finish(); |
| | 13103 | switch (windows.GetLastError()) { |
| 13100 | else => |err| return windows.unexpectedError(err), | 13104 | else => |err| return windows.unexpectedError(err), |
| 13101 | }, | 13105 | } |
| 13102 | else => return error.Unexpected, | 13106 | }, |
| 13103 | } | 13107 | else => return syscall.fail(error.Unexpected), |
| 13104 | } | 13108 | }; |
| 13105 | | 13109 | |
| 13106 | const term: process.Child.Term = x: { | 13110 | const term: process.Child.Term = x: { |
| 13107 | var exit_code: windows.DWORD = undefined; | 13111 | var exit_code: windows.DWORD = undefined; |
| ... | @@ -13142,7 +13146,7 @@ fn childCleanupWindows(child: *process.Child) void { | ... | @@ -13142,7 +13146,7 @@ fn childCleanupWindows(child: *process.Child) void { |
| 13142 | } | 13146 | } |
| 13143 | } | 13147 | } |
| 13144 | | 13148 | |
| 13145 | fn childWaitPosix(current_thread: *Thread, child: *process.Child) process.Child.WaitError!process.Child.Term { | 13149 | fn childWaitPosix(child: *process.Child) process.Child.WaitError!process.Child.Term { |
| 13146 | defer childCleanupPosix(child); | 13150 | defer childCleanupPosix(child); |
| 13147 | | 13151 | |
| 13148 | const pid = child.id.?; | 13152 | const pid = child.id.?; |
| ... | @@ -13152,29 +13156,29 @@ fn childWaitPosix(current_thread: *Thread, child: *process.Child) process.Child. | ... | @@ -13152,29 +13156,29 @@ fn childWaitPosix(current_thread: *Thread, child: *process.Child) process.Child. |
| 13152 | | 13156 | |
| 13153 | if (have_wait4) { | 13157 | if (have_wait4) { |
| 13154 | var status: if (builtin.link_libc) c_int else u32 = undefined; | 13158 | var status: if (builtin.link_libc) c_int else u32 = undefined; |
| 13155 | try current_thread.beginSyscall(); | 13159 | const syscall: Syscall = try .start(); |
| 13156 | while (true) switch (posix.errno(posix.system.wait4(pid, &status, 0, ru_ptr))) { | 13160 | while (true) switch (posix.errno(posix.system.wait4(pid, &status, 0, ru_ptr))) { |
| 13157 | .SUCCESS => { | 13161 | .SUCCESS => { |
| 13158 | current_thread.endSyscall(); | 13162 | syscall.finish(); |
| 13159 | if (ru_ptr) |p| child.resource_usage_statistics.rusage = p.*; | 13163 | if (ru_ptr) |p| child.resource_usage_statistics.rusage = p.*; |
| 13160 | return statusToTerm(@bitCast(status)); | 13164 | return statusToTerm(@bitCast(status)); |
| 13161 | }, | 13165 | }, |
| 13162 | .INTR => { | 13166 | .INTR => { |
| 13163 | try current_thread.checkCancel(); | 13167 | try syscall.checkCancel(); |
| 13164 | continue; | 13168 | continue; |
| 13165 | }, | 13169 | }, |
| 13166 | .CHILD => |err| return current_thread.endSyscallErrnoBug(err), // Double-free. | 13170 | .CHILD => |err| return syscall.errnoBug(err), // Double-free. |
| 13167 | else => |err| return current_thread.endSyscallUnexpectedErrno(err), | 13171 | else => |err| return syscall.unexpectedErrno(err), |
| 13168 | }; | 13172 | }; |
| 13169 | } | 13173 | } |
| 13170 | | 13174 | |
| 13171 | if (have_waitid) { | 13175 | if (have_waitid) { |
| 13172 | const linux = std.os.linux; // Bypass libc which has the wrong signature. | 13176 | const linux = std.os.linux; // Bypass libc which has the wrong signature. |
| 13173 | var info: linux.siginfo_t = undefined; | 13177 | var info: linux.siginfo_t = undefined; |
| 13174 | try current_thread.beginSyscall(); | 13178 | const syscall: Syscall = try .start(); |
| 13175 | while (true) switch (linux.errno(linux.waitid(.PID, pid, &info, linux.W.EXITED, ru_ptr))) { | 13179 | while (true) switch (linux.errno(linux.waitid(.PID, pid, &info, linux.W.EXITED, ru_ptr))) { |
| 13176 | .SUCCESS => { | 13180 | .SUCCESS => { |
| 13177 | current_thread.endSyscall(); | 13181 | syscall.finish(); |
| 13178 | if (ru_ptr) |p| child.resource_usage_statistics.rusage = p.*; | 13182 | if (ru_ptr) |p| child.resource_usage_statistics.rusage = p.*; |
| 13179 | const status: u32 = @bitCast(info.fields.common.second.sigchld.status); | 13183 | const status: u32 = @bitCast(info.fields.common.second.sigchld.status); |
| 13180 | const code: linux.CLD = @enumFromInt(info.code); | 13184 | const code: linux.CLD = @enumFromInt(info.code); |
| ... | @@ -13186,26 +13190,27 @@ fn childWaitPosix(current_thread: *Thread, child: *process.Child) process.Child. | ... | @@ -13186,26 +13190,27 @@ fn childWaitPosix(current_thread: *Thread, child: *process.Child) process.Child. |
| 13186 | }; | 13190 | }; |
| 13187 | }, | 13191 | }, |
| 13188 | .INTR => { | 13192 | .INTR => { |
| 13189 | try current_thread.checkCancel(); | 13193 | try syscall.checkCancel(); |
| 13190 | continue; | 13194 | continue; |
| 13191 | }, | 13195 | }, |
| 13192 | .CHILD => |err| return current_thread.endSyscallErrnoBug(err), // Double-free. | 13196 | .CHILD => |err| return syscall.errnoBug(err), // Double-free. |
| 13193 | else => |err| return current_thread.endSyscallUnexpectedErrno(err), | 13197 | else => |err| return syscall.unexpectedErrno(err), |
| 13194 | }; | 13198 | }; |
| 13195 | } | 13199 | } |
| 13196 | | 13200 | |
| 13197 | var status: if (builtin.link_libc) c_int else u32 = undefined; | 13201 | var status: if (builtin.link_libc) c_int else u32 = undefined; |
| | 13202 | const syscall: Syscall = try .start(); |
| 13198 | while (true) switch (posix.errno(posix.system.waitpid(pid, &status, 0))) { | 13203 | while (true) switch (posix.errno(posix.system.waitpid(pid, &status, 0))) { |
| 13199 | .SUCCESS => { | 13204 | .SUCCESS => { |
| 13200 | current_thread.endSyscall(); | 13205 | syscall.finish(); |
| 13201 | return statusToTerm(@bitCast(status)); | 13206 | return statusToTerm(@bitCast(status)); |
| 13202 | }, | 13207 | }, |
| 13203 | .INTR => { | 13208 | .INTR => { |
| 13204 | try current_thread.checkCancel(); | 13209 | try syscall.checkCancel(); |
| 13205 | continue; | 13210 | continue; |
| 13206 | }, | 13211 | }, |
| 13207 | .CHILD => |err| return current_thread.endSyscallErrnoBug(err), // Double-free. | 13212 | .CHILD => |err| return syscall.errnoBug(err), // Double-free. |
| 13208 | else => |err| return current_thread.endSyscallUnexpectedErrno(err), | 13213 | else => |err| return syscall.unexpectedErrno(err), |
| 13209 | }; | 13214 | }; |
| 13210 | } | 13215 | } |
| 13211 | | 13216 | |
| ... | @@ -13220,9 +13225,12 @@ fn statusToTerm(status: u32) process.Child.Term { | ... | @@ -13220,9 +13225,12 @@ fn statusToTerm(status: u32) process.Child.Term { |
| 13220 | .{ .unknown = status }; | 13225 | .{ .unknown = status }; |
| 13221 | } | 13226 | } |
| 13222 | | 13227 | |
| 13223 | fn childKillPosix(current_thread: *Thread, child: *process.Child) !void { | 13228 | fn childKillPosix(child: *process.Child) !void { |
| 13224 | // Intentionally uncancelable. | 13229 | // Entire function body is intentionally uncancelable. |
| 13225 | while (true) switch (posix.errno(posix.system.kill(child.id.?, .TERM))) { | 13230 | |
| | 13231 | const pid = child.id.?; |
| | 13232 | |
| | 13233 | while (true) switch (posix.errno(posix.system.kill(pid, .TERM))) { |
| 13226 | .SUCCESS => break, | 13234 | .SUCCESS => break, |
| 13227 | .INTR => continue, | 13235 | .INTR => continue, |
| 13228 | .PERM => return error.PermissionDenied, | 13236 | .PERM => return error.PermissionDenied, |
| ... | @@ -13230,7 +13238,35 @@ fn childKillPosix(current_thread: *Thread, child: *process.Child) !void { | ... | @@ -13230,7 +13238,35 @@ fn childKillPosix(current_thread: *Thread, child: *process.Child) !void { |
| 13230 | .SRCH => |err| return errnoBug(err), | 13238 | .SRCH => |err| return errnoBug(err), |
| 13231 | else => |err| return posix.unexpectedErrno(err), | 13239 | else => |err| return posix.unexpectedErrno(err), |
| 13232 | }; | 13240 | }; |
| 13233 | _ = try childWaitPosix(current_thread, child); | 13241 | |
| | 13242 | if (have_wait4) { |
| | 13243 | var status: if (builtin.link_libc) c_int else u32 = undefined; |
| | 13244 | while (true) switch (posix.errno(posix.system.wait4(pid, &status, 0, null))) { |
| | 13245 | .SUCCESS => return, |
| | 13246 | .INTR => continue, |
| | 13247 | .CHILD => |err| return errnoBug(err), // Double-free. |
| | 13248 | else => |err| return posix.unexpectedErrno(err), |
| | 13249 | }; |
| | 13250 | } |
| | 13251 | |
| | 13252 | if (have_waitid) { |
| | 13253 | const linux = std.os.linux; // Bypass libc which has the wrong signature. |
| | 13254 | var info: linux.siginfo_t = undefined; |
| | 13255 | while (true) switch (linux.errno(linux.waitid(.PID, pid, &info, linux.W.EXITED, null))) { |
| | 13256 | .SUCCESS => return, |
| | 13257 | .INTR => continue, |
| | 13258 | .CHILD => |err| return errnoBug(err), // Double-free. |
| | 13259 | else => |err| return posix.unexpectedErrno(err), |
| | 13260 | }; |
| | 13261 | } |
| | 13262 | |
| | 13263 | var status: if (builtin.link_libc) c_int else u32 = undefined; |
| | 13264 | while (true) switch (posix.errno(posix.system.waitpid(pid, &status, 0))) { |
| | 13265 | .SUCCESS => return, |
| | 13266 | .INTR => continue, |
| | 13267 | .CHILD => |err| return errnoBug(err), // Double-free. |
| | 13268 | else => |err| return posix.unexpectedErrno(err), |
| | 13269 | }; |
| 13234 | } | 13270 | } |
| 13235 | | 13271 | |
| 13236 | fn childCleanupPosix(child: *process.Child) void { | 13272 | fn childCleanupPosix(child: *process.Child) void { |
| ... | @@ -13537,7 +13573,6 @@ fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) pro | ... | @@ -13537,7 +13573,6 @@ fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) pro |
| 13537 | } | 13573 | } |
| 13538 | | 13574 | |
| 13539 | windowsCreateProcessPathExt( | 13575 | windowsCreateProcessPathExt( |
| 13540 | t, | | |
| 13541 | arena, | 13576 | arena, |
| 13542 | &dir_buf, | 13577 | &dir_buf, |
| 13543 | &app_buf, | 13578 | &app_buf, |
| ... | @@ -13573,7 +13608,6 @@ fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) pro | ... | @@ -13573,7 +13608,6 @@ fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) pro |
| 13573 | try dir_buf.appendSlice(arena, search_path); | 13608 | try dir_buf.appendSlice(arena, search_path); |
| 13574 | | 13609 | |
| 13575 | if (windowsCreateProcessPathExt( | 13610 | if (windowsCreateProcessPathExt( |
| 13576 | t, | | |
| 13577 | arena, | 13611 | arena, |
| 13578 | &dir_buf, | 13612 | &dir_buf, |
| 13579 | &app_buf, | 13613 | &app_buf, |