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