| ... | ... | @@ -12790,9 +12790,15 @@ fn processSpawnUnsupported(userdata: ?*anyopaque, options: process.SpawnOptions) |
| 12790 | 12790 | return error.Unexpected; |
| 12791 | 12791 | } |
| 12792 | 12792 | |
| 12793 | | fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) process.SpawnError!process.Child { |
| 12794 | | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 12793 | const Spawned = struct { |
| 12794 | pid: posix.pid_t, |
| 12795 | err_fd: posix.fd_t, |
| 12796 | stdin: ?File, |
| 12797 | stdout: ?File, |
| 12798 | stderr: ?File, |
| 12799 | }; |
| 12795 | 12800 | |
| 12801 | fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Spawned { |
| 12796 | 12802 | // The child process does need to access (one end of) these pipes. However, |
| 12797 | 12803 | // we must initially set CLOEXEC to avoid a race condition. If another thread |
| 12798 | 12804 | // is racing to spawn a different child process, we don't want it to inherit |
| ... | ... | @@ -12947,9 +12953,9 @@ fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) proce |
| 12947 | 12953 | } |
| 12948 | 12954 | |
| 12949 | 12955 | const pid: posix.pid_t = @intCast(pid_result); // We are the parent. |
| 12956 | errdefer comptime unreachable; // The child is forked; we must not error from now on |
| 12950 | 12957 | |
| 12951 | 12958 | posix.close(err_pipe[1]); // make sure only the child holds the write end open |
| 12952 | | defer posix.close(err_pipe[0]); |
| 12953 | 12959 | |
| 12954 | 12960 | if (options.stdin == .pipe) posix.close(stdin_pipe[0]); |
| 12955 | 12961 | if (options.stdout == .pipe) posix.close(stdout_pipe[1]); |
| ... | ... | @@ -12959,8 +12965,31 @@ fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) proce |
| 12959 | 12965 | |
| 12960 | 12966 | options.progress_node.setIpcFd(prog_pipe[0]); |
| 12961 | 12967 | |
| 12968 | return .{ |
| 12969 | .pid = pid, |
| 12970 | .err_fd = err_pipe[0], |
| 12971 | .stdin = switch (options.stdin) { |
| 12972 | .pipe => .{ .handle = stdin_pipe[1] }, |
| 12973 | else => null, |
| 12974 | }, |
| 12975 | .stdout = switch (options.stdout) { |
| 12976 | .pipe => .{ .handle = stdout_pipe[0] }, |
| 12977 | else => null, |
| 12978 | }, |
| 12979 | .stderr = switch (options.stderr) { |
| 12980 | .pipe => .{ .handle = stderr_pipe[0] }, |
| 12981 | else => null, |
| 12982 | }, |
| 12983 | }; |
| 12984 | } |
| 12985 | |
| 12986 | fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) process.SpawnError!process.Child { |
| 12987 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 12988 | const spawned = try spawnPosix(t, options); |
| 12989 | defer posix.close(spawned.err_fd); |
| 12990 | |
| 12962 | 12991 | // Wait for the child to report any errors in or before `execvpe`. |
| 12963 | | if (readIntFd(t, err_pipe[0])) |child_err_int| { |
| 12992 | if (readIntFd(t, spawned.err_fd)) |child_err_int| { |
| 12964 | 12993 | const child_err: process.SpawnError = @errorCast(@errorFromInt(child_err_int)); |
| 12965 | 12994 | return child_err; |
| 12966 | 12995 | } else |read_err| switch (read_err) { |
| ... | ... | @@ -12976,20 +13005,11 @@ fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) proce |
| 12976 | 13005 | } |
| 12977 | 13006 | |
| 12978 | 13007 | return .{ |
| 12979 | | .id = pid, |
| 13008 | .id = spawned.pid, |
| 12980 | 13009 | .thread_handle = {}, |
| 12981 | | .stdin = switch (options.stdin) { |
| 12982 | | .pipe => .{ .handle = stdin_pipe[1] }, |
| 12983 | | else => null, |
| 12984 | | }, |
| 12985 | | .stdout = switch (options.stdout) { |
| 12986 | | .pipe => .{ .handle = stdout_pipe[0] }, |
| 12987 | | else => null, |
| 12988 | | }, |
| 12989 | | .stderr = switch (options.stderr) { |
| 12990 | | .pipe => .{ .handle = stderr_pipe[0] }, |
| 12991 | | else => null, |
| 12992 | | }, |
| 13010 | .stdin = spawned.stdin, |
| 13011 | .stdout = spawned.stdout, |
| 13012 | .stderr = spawned.stderr, |
| 12993 | 13013 | .request_resource_usage_statistics = options.request_resource_usage_statistics, |
| 12994 | 13014 | }; |
| 12995 | 13015 | } |
| ... | ... | @@ -13156,10 +13176,13 @@ fn forkBail(fd: posix.fd_t, err: ForkBailError) noreturn { |
| 13156 | 13176 | // it caused a deadlock instead of doing an exit syscall. In the words of Avril Lavigne, |
| 13157 | 13177 | // "Why'd you have to go and make things so complicated?" |
| 13158 | 13178 | if (builtin.link_libc) { |
| 13159 | | // The _exit(2) function does nothing but make the exit syscall, unlike exit(3) |
| 13179 | // The `_exit` function does nothing but make the exit syscall, unlike `exit`. |
| 13160 | 13180 | std.c._exit(1); |
| 13181 | } else if (native_os == .linux and !builtin.single_threaded) { |
| 13182 | std.os.linux.exit_group(1); |
| 13183 | } else { |
| 13184 | posix.system.exit(1); |
| 13161 | 13185 | } |
| 13162 | | posix.system.exit(1); |
| 13163 | 13186 | } |
| 13164 | 13187 | |
| 13165 | 13188 | fn writeIntFd(fd: posix.fd_t, value: ErrInt) !void { |
| ... | ... | @@ -13190,7 +13213,7 @@ fn readIntFd(t: *Threaded, fd: posix.fd_t) !ErrInt { |
| 13190 | 13213 | switch (posix.errno(rc)) { |
| 13191 | 13214 | .SUCCESS => { |
| 13192 | 13215 | const n: usize = @intCast(rc); |
| 13193 | | if (n == 0) return error.EndOfStream; |
| 13216 | if (n == 0) break; |
| 13194 | 13217 | i += n; |
| 13195 | 13218 | continue; |
| 13196 | 13219 | }, |
| ... | ... | @@ -13198,6 +13221,7 @@ fn readIntFd(t: *Threaded, fd: posix.fd_t) !ErrInt { |
| 13198 | 13221 | else => |err| return posix.unexpectedErrno(err), |
| 13199 | 13222 | } |
| 13200 | 13223 | } |
| 13224 | if (buffer.len - i != 0) return error.EndOfStream; |
| 13201 | 13225 | return @intCast(std.mem.readInt(u64, &buffer, .little)); |
| 13202 | 13226 | } |
| 13203 | 13227 | |
| ... | ... | @@ -14371,9 +14395,9 @@ pub fn execvpeZ( |
| 14371 | 14395 | file: [*:0]const u8, |
| 14372 | 14396 | argv_ptr: [*:null]const ?[*:0]const u8, |
| 14373 | 14397 | envp: [*:null]const ?[*:0]const u8, |
| 14374 | | optional_PATH: ?[]const u8, |
| 14398 | PATH: []const u8, |
| 14375 | 14399 | ) process.ReplaceError { |
| 14376 | | return execvpeZ_expandArg0(.no_expand, file, argv_ptr, envp, optional_PATH); |
| 14400 | return execvpeZ_expandArg0(.no_expand, file, argv_ptr, envp, PATH); |
| 14377 | 14401 | } |
| 14378 | 14402 | |
| 14379 | 14403 | fn windowsMakePipeIn(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const windows.SECURITY_ATTRIBUTES) !void { |