authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-03 17:32:22-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-04 00:27:09-08:00
log08d8b412e9217018d760666094b89918de02f10e
tree89660d02de24066ec95623136b2e700eb2e6f88e
parentf072313e1e8881dcd3b360b03e30397d705c1d00

std.Io.Threaded: more robust windows process creation error handling


1 files changed, 84 insertions(+), 50 deletions(-)

lib/std/Io/Threaded.zig+84-50
...@@ -13780,7 +13780,29 @@ fn windowsCreateProcessPathExt(...@@ -13780,7 +13780,29 @@ fn windowsCreateProcessPathExt(
13780 const prefixed_path = try windows.wToPrefixedFileW(null, dir_path_z);13780 const prefixed_path = try windows.wToPrefixedFileW(null, dir_path_z);
13781 break :dir dirOpenDirWindows(.cwd(), prefixed_path.span(), .{13781 break :dir dirOpenDirWindows(.cwd(), prefixed_path.span(), .{
13782 .iterate = true,13782 .iterate = true,
13783 }) catch return error.FileNotFound;13783 }) catch |err| switch (err) {
13784 // These errors must not be ignored because they should not be able
13785 // to affect which file is chosen to execute. Also `error.Canceled`
13786 // must never be swallowed.
13787 error.Canceled,
13788 error.SystemResources,
13789 error.Unexpected,
13790 error.ProcessFdQuotaExceeded,
13791 error.SystemFdQuotaExceeded,
13792 => |e| return e,
13793
13794 error.AccessDenied,
13795 error.PermissionDenied,
13796 error.SymLinkLoop,
13797 error.FileNotFound,
13798 error.NotDir,
13799 error.NoDevice,
13800 error.NetworkNotFound,
13801 error.NameTooLong,
13802 error.BadPathName,
13803 error.DeviceBusy,
13804 => return error.FileNotFound,
13805 };
13784 };13806 };
13785 defer windows.CloseHandle(dir.handle);13807 defer windows.CloseHandle(dir.handle);
1378613808
...@@ -13984,55 +14006,67 @@ fn windowsCreateProcess(...@@ -13984,55 +14006,67 @@ fn windowsCreateProcess(
13984 lpStartupInfo: *windows.STARTUPINFOW,14006 lpStartupInfo: *windows.STARTUPINFOW,
13985 lpProcessInformation: *windows.PROCESS_INFORMATION,14007 lpProcessInformation: *windows.PROCESS_INFORMATION,
13986) !void {14008) !void {
13987 if (windows.kernel32.CreateProcessW(14009 const syscall: Syscall = try .start();
13988 app_name,14010 while (true) {
13989 cmd_line,14011 if (windows.kernel32.CreateProcessW(
13990 null,14012 app_name,
13991 null,14013 cmd_line,
13992 windows.TRUE,14014 null,
13993 flags,14015 null,
13994 env_ptr,14016 windows.TRUE,
13995 cwd_ptr,14017 flags,
13996 lpStartupInfo,14018 env_ptr,
13997 lpProcessInformation,14019 cwd_ptr,
13998 ) == 0) switch (windows.GetLastError()) {14020 lpStartupInfo,
13999 .FILE_NOT_FOUND => return error.FileNotFound,14021 lpProcessInformation,
14000 .PATH_NOT_FOUND => return error.FileNotFound,14022 ) != 0) {
14001 .DIRECTORY => return error.FileNotFound,14023 return syscall.finish();
14002 .ACCESS_DENIED => return error.AccessDenied,14024 } else switch (windows.GetLastError()) {
14003 .INVALID_PARAMETER => unreachable,14025 .INVALID_PARAMETER => unreachable,
14004 .INVALID_NAME => return error.InvalidName,14026 .OPERATION_ABORTED => {
14005 .FILENAME_EXCED_RANGE => return error.NameTooLong,14027 try syscall.checkCancel();
14006 .SHARING_VIOLATION => return error.FileBusy,14028 continue;
1400714029 },
14008 // These are all the system errors that are mapped to ENOEXEC by14030 .FILE_NOT_FOUND => return syscall.fail(error.FileNotFound),
14009 // the undocumented _dosmaperr (old CRT) or __acrt_errno_map_os_error14031 .PATH_NOT_FOUND => return syscall.fail(error.FileNotFound),
14010 // (newer CRT) functions. Their code can be found in crt/src/dosmap.c (old SDK)14032 .DIRECTORY => return syscall.fail(error.FileNotFound),
14011 // or urt/misc/errno.cpp (newer SDK) in the Windows SDK.14033 .ACCESS_DENIED => return syscall.fail(error.AccessDenied),
14012 .BAD_FORMAT,14034 .INVALID_NAME => return syscall.fail(error.InvalidName),
14013 .INVALID_STARTING_CODESEG, // MIN_EXEC_ERROR in errno.cpp14035 .FILENAME_EXCED_RANGE => return syscall.fail(error.NameTooLong),
14014 .INVALID_STACKSEG,14036 .SHARING_VIOLATION => return syscall.fail(error.FileBusy),
14015 .INVALID_MODULETYPE,14037 .COMMITMENT_LIMIT => return syscall.fail(error.SystemResources),
14016 .INVALID_EXE_SIGNATURE,14038
14017 .EXE_MARKED_INVALID,14039 // These are all the system errors that are mapped to ENOEXEC by
14018 .BAD_EXE_FORMAT,14040 // the undocumented _dosmaperr (old CRT) or __acrt_errno_map_os_error
14019 .ITERATED_DATA_EXCEEDS_64k,14041 // (newer CRT) functions. Their code can be found in crt/src/dosmap.c (old SDK)
14020 .INVALID_MINALLOCSIZE,14042 // or urt/misc/errno.cpp (newer SDK) in the Windows SDK.
14021 .DYNLINK_FROM_INVALID_RING,14043 .BAD_FORMAT,
14022 .IOPL_NOT_ENABLED,14044 .INVALID_STARTING_CODESEG, // MIN_EXEC_ERROR in errno.cpp
14023 .INVALID_SEGDPL,14045 .INVALID_STACKSEG,
14024 .AUTODATASEG_EXCEEDS_64k,14046 .INVALID_MODULETYPE,
14025 .RING2SEG_MUST_BE_MOVABLE,14047 .INVALID_EXE_SIGNATURE,
14026 .RELOC_CHAIN_XEEDS_SEGLIM,14048 .EXE_MARKED_INVALID,
14027 .INFLOOP_IN_RELOC_CHAIN, // MAX_EXEC_ERROR in errno.cpp14049 .BAD_EXE_FORMAT,
14028 // This one is not mapped to ENOEXEC but it is possible, for example14050 .ITERATED_DATA_EXCEEDS_64k,
14029 // when calling CreateProcessW on a plain text file with a .exe extension14051 .INVALID_MINALLOCSIZE,
14030 .EXE_MACHINE_TYPE_MISMATCH,14052 .DYNLINK_FROM_INVALID_RING,
14031 => return error.InvalidExe,14053 .IOPL_NOT_ENABLED,
1403214054 .INVALID_SEGDPL,
14033 .COMMITMENT_LIMIT => return error.SystemResources,14055 .AUTODATASEG_EXCEEDS_64k,
14034 else => |err| return windows.unexpectedError(err),14056 .RING2SEG_MUST_BE_MOVABLE,
14035 };14057 .RELOC_CHAIN_XEEDS_SEGLIM,
14058 .INFLOOP_IN_RELOC_CHAIN, // MAX_EXEC_ERROR in errno.cpp
14059 // This one is not mapped to ENOEXEC but it is possible, for example
14060 // when calling CreateProcessW on a plain text file with a .exe extension
14061 .EXE_MACHINE_TYPE_MISMATCH,
14062 => return syscall.fail(error.InvalidExe),
14063
14064 else => |err| {
14065 syscall.finish();
14066 return windows.unexpectedError(err);
14067 },
14068 }
14069 }
14036}14070}
1403714071
14038/// Case-insensitive WTF-16 lookup14072/// Case-insensitive WTF-16 lookup