| ... | @@ -142,7 +142,7 @@ pub const ChildProcess = struct { | ... | @@ -142,7 +142,7 @@ pub const ChildProcess = struct { |
| 142 | if (!windows.TerminateProcess(self.handle, exit_code)) { | 142 | if (!windows.TerminateProcess(self.handle, exit_code)) { |
| 143 | const err = windows.GetLastError(); | 143 | const err = windows.GetLastError(); |
| 144 | return switch (err) { | 144 | return switch (err) { |
| 145 | else => error.Unexpected, | 145 | else => os.unexpectedErrorWindows(err), |
| 146 | }; | 146 | }; |
| 147 | } | 147 | } |
| 148 | self.waitUnwrappedWindows(); | 148 | self.waitUnwrappedWindows(); |
| ... | @@ -164,7 +164,7 @@ pub const ChildProcess = struct { | ... | @@ -164,7 +164,7 @@ pub const ChildProcess = struct { |
| 164 | posix.EINVAL => unreachable, | 164 | posix.EINVAL => unreachable, |
| 165 | posix.EPERM => error.PermissionDenied, | 165 | posix.EPERM => error.PermissionDenied, |
| 166 | posix.ESRCH => error.ProcessNotFound, | 166 | posix.ESRCH => error.ProcessNotFound, |
| 167 | else => error.Unexpected, | 167 | else => os.unexpectedErrorPosix(err), |
| 168 | }; | 168 | }; |
| 169 | } | 169 | } |
| 170 | self.waitUnwrapped(); | 170 | self.waitUnwrapped(); |
| ... | @@ -357,7 +357,7 @@ pub const ChildProcess = struct { | ... | @@ -357,7 +357,7 @@ pub const ChildProcess = struct { |
| 357 | restore_SIGCHLD(); | 357 | restore_SIGCHLD(); |
| 358 | return switch (pid_err) { | 358 | return switch (pid_err) { |
| 359 | posix.EAGAIN, posix.ENOMEM, posix.ENOSYS => error.SystemResources, | 359 | posix.EAGAIN, posix.ENOMEM, posix.ENOSYS => error.SystemResources, |
| 360 | else => error.Unexpected, | 360 | else => os.unexpectedErrorPosix(pid_err), |
| 361 | }; | 361 | }; |
| 362 | } | 362 | } |
| 363 | if (pid_result == 0) { | 363 | if (pid_result == 0) { |
| ... | @@ -556,9 +556,6 @@ pub const ChildProcess = struct { | ... | @@ -556,9 +556,6 @@ pub const ChildProcess = struct { |
| 556 | }; | 556 | }; |
| 557 | var piProcInfo: windows.PROCESS_INFORMATION = undefined; | 557 | var piProcInfo: windows.PROCESS_INFORMATION = undefined; |
| 558 | | 558 | |
| 559 | const app_name = %return cstr.addNullByte(self.allocator, self.argv[0]); | | |
| 560 | defer self.allocator.free(app_name); | | |
| 561 | | | |
| 562 | const cwd_slice = if (self.cwd) |cwd| { | 559 | const cwd_slice = if (self.cwd) |cwd| { |
| 563 | %return cstr.addNullByte(self.allocator, cwd) | 560 | %return cstr.addNullByte(self.allocator, cwd) |
| 564 | } else { | 561 | } else { |
| ... | @@ -575,17 +572,42 @@ pub const ChildProcess = struct { | ... | @@ -575,17 +572,42 @@ pub const ChildProcess = struct { |
| 575 | defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf); | 572 | defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf); |
| 576 | const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null; | 573 | const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null; |
| 577 | | 574 | |
| 578 | if (windows.CreateProcessA(app_name.ptr, cmd_line.ptr, null, null, windows.TRUE, 0, | 575 | // the cwd set in ChildProcess is in effect when choosing the executable path |
| 579 | @ptrCast(?&c_void, envp_ptr), | 576 | // to match posix semantics |
| 580 | cwd_ptr, &siStartInfo, &piProcInfo) == windows.FALSE) | 577 | const app_name = if (self.cwd) |cwd| { |
| | 578 | const resolved = %return os.path.resolve(self.allocator, cwd, self.argv[0]); |
| | 579 | defer self.allocator.free(resolved); |
| | 580 | %return cstr.addNullByte(self.allocator, resolved) |
| | 581 | } else { |
| | 582 | %return cstr.addNullByte(self.allocator, self.argv[0]) |
| | 583 | }; |
| | 584 | defer self.allocator.free(app_name); |
| | 585 | |
| | 586 | windowsCreateProcess(app_name.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, |
| | 587 | &siStartInfo, &piProcInfo) %% |no_path_err| |
| 581 | { | 588 | { |
| 582 | const err = windows.GetLastError(); | 589 | if (no_path_err != error.FileNotFound) |
| 583 | return switch (err) { | 590 | return no_path_err; |
| 584 | windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, | 591 | |
| 585 | windows.ERROR.INVALID_PARAMETER => unreachable, | 592 | const PATH = %return os.getEnvVarOwned(self.allocator, "PATH"); |
| 586 | else => error.Unexpected, | 593 | defer self.allocator.free(PATH); |
| 587 | }; | 594 | |
| 588 | } | 595 | var it = mem.split(PATH, ";"); |
| | 596 | while (it.next()) |search_path| { |
| | 597 | const joined_path = %return os.path.join(self.allocator, search_path, app_name); |
| | 598 | defer self.allocator.free(joined_path); |
| | 599 | |
| | 600 | if (windowsCreateProcess(joined_path.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, |
| | 601 | &siStartInfo, &piProcInfo)) |_| |
| | 602 | { |
| | 603 | break; |
| | 604 | } else |err| if (err == error.FileNotFound) { |
| | 605 | continue; |
| | 606 | } else { |
| | 607 | return err; |
| | 608 | } |
| | 609 | } |
| | 610 | }; |
| 589 | | 611 | |
| 590 | if (stdin_ptr) |outstream| { | 612 | if (stdin_ptr) |outstream| { |
| 591 | *outstream = io.OutStream { | 613 | *outstream = io.OutStream { |
| ... | @@ -633,6 +655,24 @@ pub const ChildProcess = struct { | ... | @@ -633,6 +655,24 @@ pub const ChildProcess = struct { |
| 633 | } | 655 | } |
| 634 | }; | 656 | }; |
| 635 | | 657 | |
| | 658 | fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, |
| | 659 | lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) -> %void |
| | 660 | { |
| | 661 | if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, |
| | 662 | @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) |
| | 663 | { |
| | 664 | const err = windows.GetLastError(); |
| | 665 | return switch (err) { |
| | 666 | windows.ERROR.FILE_NOT_FOUND, windows.ERROR.PATH_NOT_FOUND => error.FileNotFound, |
| | 667 | windows.ERROR.INVALID_PARAMETER => unreachable, |
| | 668 | else => os.unexpectedErrorWindows(err), |
| | 669 | }; |
| | 670 | } |
| | 671 | } |
| | 672 | |
| | 673 | |
| | 674 | |
| | 675 | |
| 636 | /// Caller must dealloc. | 676 | /// Caller must dealloc. |
| 637 | /// Guarantees a null byte at result[result.len]. | 677 | /// Guarantees a null byte at result[result.len]. |
| 638 | fn windowsCreateCommandLine(allocator: &Allocator, argv: []const []const u8) -> %[]u8 { | 678 | fn windowsCreateCommandLine(allocator: &Allocator, argv: []const []const u8) -> %[]u8 { |
| ... | @@ -684,7 +724,7 @@ fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECUR | ... | @@ -684,7 +724,7 @@ fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECUR |
| 684 | if (windows.CreatePipe(rd, wr, sattr, 0) == 0) { | 724 | if (windows.CreatePipe(rd, wr, sattr, 0) == 0) { |
| 685 | const err = windows.GetLastError(); | 725 | const err = windows.GetLastError(); |
| 686 | return switch (err) { | 726 | return switch (err) { |
| 687 | else => error.Unexpected, | 727 | else => os.unexpectedErrorWindows(err), |
| 688 | }; | 728 | }; |
| 689 | } | 729 | } |
| 690 | } | 730 | } |
| ... | @@ -693,7 +733,7 @@ fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.D | ... | @@ -693,7 +733,7 @@ fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.D |
| 693 | if (windows.SetHandleInformation(h, mask, flags) == 0) { | 733 | if (windows.SetHandleInformation(h, mask, flags) == 0) { |
| 694 | const err = windows.GetLastError(); | 734 | const err = windows.GetLastError(); |
| 695 | return switch (err) { | 735 | return switch (err) { |
| 696 | else => error.Unexpected, | 736 | else => os.unexpectedErrorWindows(err), |
| 697 | }; | 737 | }; |
| 698 | } | 738 | } |
| 699 | } | 739 | } |
| ... | @@ -724,7 +764,7 @@ fn makePipe() -> %[2]i32 { | ... | @@ -724,7 +764,7 @@ fn makePipe() -> %[2]i32 { |
| 724 | if (err > 0) { | 764 | if (err > 0) { |
| 725 | return switch (err) { | 765 | return switch (err) { |
| 726 | posix.EMFILE, posix.ENFILE => error.SystemResources, | 766 | posix.EMFILE, posix.ENFILE => error.SystemResources, |
| 727 | else => error.Unexpected, | 767 | else => os.unexpectedErrorPosix(err), |
| 728 | } | 768 | } |
| 729 | } | 769 | } |
| 730 | return fds; | 770 | return fds; |