| ... | @@ -80,9 +80,13 @@ expand_arg0: Arg0Expand, | ... | @@ -80,9 +80,13 @@ expand_arg0: Arg0Expand, |
| 80 | /// Darwin-only. Disable ASLR for the child process. | 80 | /// Darwin-only. Disable ASLR for the child process. |
| 81 | disable_aslr: bool = false, | 81 | disable_aslr: bool = false, |
| 82 | | 82 | |
| 83 | /// Darwin-only. Start child process in suspended state as if SIGSTOP was sent. | 83 | /// Darwin and Windows only. Start child process in suspended state. For Darwin it's started |
| | 84 | /// as if SIGSTOP was sent. |
| 84 | start_suspended: bool = false, | 85 | start_suspended: bool = false, |
| 85 | | 86 | |
| | 87 | /// Windows-only. Sets the CREATE_NO_WINDOW flag in CreateProcess. |
| | 88 | create_no_window: bool = false, |
| | 89 | |
| 86 | /// Set to true to obtain rusage information for the child process. | 90 | /// Set to true to obtain rusage information for the child process. |
| 87 | /// Depending on the target platform and implementation status, the | 91 | /// Depending on the target platform and implementation status, the |
| 88 | /// requested statistics may or may not be available. If they are | 92 | /// requested statistics may or may not be available. If they are |
| ... | @@ -854,6 +858,12 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { | ... | @@ -854,6 +858,12 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { |
| 854 | const app_name_w = try unicode.wtf8ToWtf16LeAllocZ(self.allocator, app_basename_wtf8); | 858 | const app_name_w = try unicode.wtf8ToWtf16LeAllocZ(self.allocator, app_basename_wtf8); |
| 855 | defer self.allocator.free(app_name_w); | 859 | defer self.allocator.free(app_name_w); |
| 856 | | 860 | |
| | 861 | const flags: windows.CreateProcessFlags = .{ |
| | 862 | .create_suspended = self.start_suspended, |
| | 863 | .create_unicode_environment = true, |
| | 864 | .create_no_window = self.create_no_window, |
| | 865 | }; |
| | 866 | |
| 857 | run: { | 867 | run: { |
| 858 | const PATH: [:0]const u16 = process.getenvW(unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse &[_:0]u16{}; | 868 | const PATH: [:0]const u16 = process.getenvW(unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse &[_:0]u16{}; |
| 859 | const PATHEXT: [:0]const u16 = process.getenvW(unicode.utf8ToUtf16LeStringLiteral("PATHEXT")) orelse &[_:0]u16{}; | 869 | const PATHEXT: [:0]const u16 = process.getenvW(unicode.utf8ToUtf16LeStringLiteral("PATHEXT")) orelse &[_:0]u16{}; |
| ... | @@ -889,7 +899,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { | ... | @@ -889,7 +899,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { |
| 889 | dir_buf.shrinkRetainingCapacity(normalized_len); | 899 | dir_buf.shrinkRetainingCapacity(normalized_len); |
| 890 | } | 900 | } |
| 891 | | 901 | |
| 892 | windowsCreateProcessPathExt(self.allocator, &dir_buf, &app_buf, PATHEXT, &cmd_line_cache, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo) catch |no_path_err| { | 902 | windowsCreateProcessPathExt(self.allocator, &dir_buf, &app_buf, PATHEXT, &cmd_line_cache, envp_ptr, cwd_w_ptr, flags, &siStartInfo, &piProcInfo) catch |no_path_err| { |
| 893 | const original_err = switch (no_path_err) { | 903 | const original_err = switch (no_path_err) { |
| 894 | // argv[0] contains unsupported characters that will never resolve to a valid exe. | 904 | // argv[0] contains unsupported characters that will never resolve to a valid exe. |
| 895 | error.InvalidArg0 => return error.FileNotFound, | 905 | error.InvalidArg0 => return error.FileNotFound, |
| ... | @@ -917,7 +927,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { | ... | @@ -917,7 +927,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { |
| 917 | const normalized_len = windows.normalizePath(u16, dir_buf.items) catch continue; | 927 | const normalized_len = windows.normalizePath(u16, dir_buf.items) catch continue; |
| 918 | dir_buf.shrinkRetainingCapacity(normalized_len); | 928 | dir_buf.shrinkRetainingCapacity(normalized_len); |
| 919 | | 929 | |
| 920 | if (windowsCreateProcessPathExt(self.allocator, &dir_buf, &app_buf, PATHEXT, &cmd_line_cache, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo)) { | 930 | if (windowsCreateProcessPathExt(self.allocator, &dir_buf, &app_buf, PATHEXT, &cmd_line_cache, envp_ptr, cwd_w_ptr, flags, &siStartInfo, &piProcInfo)) { |
| 921 | break :run; | 931 | break :run; |
| 922 | } else |err| switch (err) { | 932 | } else |err| switch (err) { |
| 923 | // argv[0] contains unsupported characters that will never resolve to a valid exe. | 933 | // argv[0] contains unsupported characters that will never resolve to a valid exe. |
| ... | @@ -1016,6 +1026,7 @@ fn windowsCreateProcessPathExt( | ... | @@ -1016,6 +1026,7 @@ fn windowsCreateProcessPathExt( |
| 1016 | cmd_line_cache: *WindowsCommandLineCache, | 1026 | cmd_line_cache: *WindowsCommandLineCache, |
| 1017 | envp_ptr: ?[*]u16, | 1027 | envp_ptr: ?[*]u16, |
| 1018 | cwd_ptr: ?[*:0]u16, | 1028 | cwd_ptr: ?[*:0]u16, |
| | 1029 | flags: windows.CreateProcessFlags, |
| 1019 | lpStartupInfo: *windows.STARTUPINFOW, | 1030 | lpStartupInfo: *windows.STARTUPINFOW, |
| 1020 | lpProcessInformation: *windows.PROCESS_INFORMATION, | 1031 | lpProcessInformation: *windows.PROCESS_INFORMATION, |
| 1021 | ) !void { | 1032 | ) !void { |
| ... | @@ -1166,7 +1177,7 @@ fn windowsCreateProcessPathExt( | ... | @@ -1166,7 +1177,7 @@ fn windowsCreateProcessPathExt( |
| 1166 | else | 1177 | else |
| 1167 | full_app_name; | 1178 | full_app_name; |
| 1168 | | 1179 | |
| 1169 | if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, lpStartupInfo, lpProcessInformation)) |_| { | 1180 | if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, flags, lpStartupInfo, lpProcessInformation)) |_| { |
| 1170 | return; | 1181 | return; |
| 1171 | } else |err| switch (err) { | 1182 | } else |err| switch (err) { |
| 1172 | error.FileNotFound, | 1183 | error.FileNotFound, |
| ... | @@ -1221,7 +1232,7 @@ fn windowsCreateProcessPathExt( | ... | @@ -1221,7 +1232,7 @@ fn windowsCreateProcessPathExt( |
| 1221 | else | 1232 | else |
| 1222 | full_app_name; | 1233 | full_app_name; |
| 1223 | | 1234 | |
| 1224 | if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, lpStartupInfo, lpProcessInformation)) |_| { | 1235 | if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, flags, lpStartupInfo, lpProcessInformation)) |_| { |
| 1225 | return; | 1236 | return; |
| 1226 | } else |err| switch (err) { | 1237 | } else |err| switch (err) { |
| 1227 | error.FileNotFound => continue, | 1238 | error.FileNotFound => continue, |
| ... | @@ -1247,6 +1258,7 @@ fn windowsCreateProcess( | ... | @@ -1247,6 +1258,7 @@ fn windowsCreateProcess( |
| 1247 | cmd_line: [*:0]u16, | 1258 | cmd_line: [*:0]u16, |
| 1248 | envp_ptr: ?[*]u16, | 1259 | envp_ptr: ?[*]u16, |
| 1249 | cwd_ptr: ?[*:0]u16, | 1260 | cwd_ptr: ?[*:0]u16, |
| | 1261 | flags: windows.CreateProcessFlags, |
| 1250 | lpStartupInfo: *windows.STARTUPINFOW, | 1262 | lpStartupInfo: *windows.STARTUPINFOW, |
| 1251 | lpProcessInformation: *windows.PROCESS_INFORMATION, | 1263 | lpProcessInformation: *windows.PROCESS_INFORMATION, |
| 1252 | ) !void { | 1264 | ) !void { |
| ... | @@ -1273,7 +1285,7 @@ fn windowsCreateProcess( | ... | @@ -1273,7 +1285,7 @@ fn windowsCreateProcess( |
| 1273 | null, | 1285 | null, |
| 1274 | null, | 1286 | null, |
| 1275 | windows.TRUE, | 1287 | windows.TRUE, |
| 1276 | windows.CREATE_UNICODE_ENVIRONMENT, | 1288 | flags, |
| 1277 | @as(?*anyopaque, @ptrCast(envp_ptr)), | 1289 | @as(?*anyopaque, @ptrCast(envp_ptr)), |
| 1278 | cwd_ptr, | 1290 | cwd_ptr, |
| 1279 | lpStartupInfo, | 1291 | lpStartupInfo, |