authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-15 16:03:32-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-15 16:03:32-04:00
logbb169a7b36a658ed463787655df54e3f59133d98
tree773587c8f8d31ff2d892d37ad8bcc3f6e1d319a5
parent1fe1e6eeaf2f6157133546d49be6b0e0c1da3dd3

fix child process stdio piping behavior on windows


4 files changed, 22 insertions(+), 17 deletions(-)

std/io.zig+1-1
...@@ -313,8 +313,8 @@ pub const InStream = struct {...@@ -313,8 +313,8 @@ pub const InStream = struct {
313 else => error.Unexpected,313 else => error.Unexpected,
314 };314 };
315 }315 }
316 if (amt_read == 0) return index;
317 index += amt_read;316 index += amt_read;
317 if (amt_read < want_read_count) return index;
318 }318 }
319 return index;319 return index;
320 } else {320 } else {
std/os/child_process.zig+14-7
...@@ -433,7 +433,7 @@ pub const ChildProcess = struct {...@@ -433,7 +433,7 @@ pub const ChildProcess = struct {
433 }433 }
434434
435 fn spawnWindows(self: &ChildProcess) -> %void {435 fn spawnWindows(self: &ChildProcess) -> %void {
436 var saAttr = windows.SECURITY_ATTRIBUTES {436 const saAttr = windows.SECURITY_ATTRIBUTES {
437 .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES),437 .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES),
438 .bInheritHandle = windows.TRUE,438 .bInheritHandle = windows.TRUE,
439 .lpSecurityDescriptor = null,439 .lpSecurityDescriptor = null,
...@@ -459,7 +459,7 @@ pub const ChildProcess = struct {...@@ -459,7 +459,7 @@ pub const ChildProcess = struct {
459 var g_hChildStd_IN_Wr: ?windows.HANDLE = null;459 var g_hChildStd_IN_Wr: ?windows.HANDLE = null;
460 switch (self.stdin_behavior) {460 switch (self.stdin_behavior) {
461 StdIo.Pipe => {461 StdIo.Pipe => {
462 %return windowsMakePipeIn(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr);462 %return windowsMakePipeIn(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, saAttr);
463 },463 },
464 StdIo.Ignore => {464 StdIo.Ignore => {
465 g_hChildStd_IN_Rd = nul_handle;465 g_hChildStd_IN_Rd = nul_handle;
...@@ -477,7 +477,7 @@ pub const ChildProcess = struct {...@@ -477,7 +477,7 @@ pub const ChildProcess = struct {
477 var g_hChildStd_OUT_Wr: ?windows.HANDLE = null;477 var g_hChildStd_OUT_Wr: ?windows.HANDLE = null;
478 switch (self.stdout_behavior) {478 switch (self.stdout_behavior) {
479 StdIo.Pipe => {479 StdIo.Pipe => {
480 %return windowsMakePipeOut(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr);480 %return windowsMakePipeOut(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, saAttr);
481 },481 },
482 StdIo.Ignore => {482 StdIo.Ignore => {
483 g_hChildStd_OUT_Wr = nul_handle;483 g_hChildStd_OUT_Wr = nul_handle;
...@@ -495,7 +495,7 @@ pub const ChildProcess = struct {...@@ -495,7 +495,7 @@ pub const ChildProcess = struct {
495 var g_hChildStd_ERR_Wr: ?windows.HANDLE = null;495 var g_hChildStd_ERR_Wr: ?windows.HANDLE = null;
496 switch (self.stderr_behavior) {496 switch (self.stderr_behavior) {
497 StdIo.Pipe => {497 StdIo.Pipe => {
498 %return windowsMakePipeOut(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr);498 %return windowsMakePipeOut(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, saAttr);
499 },499 },
500 StdIo.Ignore => {500 StdIo.Ignore => {
501 g_hChildStd_ERR_Wr = nul_handle;501 g_hChildStd_ERR_Wr = nul_handle;
...@@ -675,7 +675,12 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) {...@@ -675,7 +675,12 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) {
675 if (wr) |h| os.windowsClose(h);675 if (wr) |h| os.windowsClose(h);
676}676}
677677
678fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &windows.SECURITY_ATTRIBUTES) -> %void {678
679// TODO: workaround for bug where the `const` from `&const` is dropped when the type is
680// a namespace field lookup
681const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES;
682
683fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void {
679 if (windows.CreatePipe(rd, wr, sattr, 0) == 0) {684 if (windows.CreatePipe(rd, wr, sattr, 0) == 0) {
680 const err = windows.GetLastError();685 const err = windows.GetLastError();
681 return switch (err) {686 return switch (err) {
...@@ -693,19 +698,21 @@ fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.D...@@ -693,19 +698,21 @@ fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.D
693 }698 }
694}699}
695700
696fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &windows.SECURITY_ATTRIBUTES) -> %void {701fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void {
697 var rd_h: windows.HANDLE = undefined;702 var rd_h: windows.HANDLE = undefined;
698 var wr_h: windows.HANDLE = undefined;703 var wr_h: windows.HANDLE = undefined;
699 %return windowsMakePipe(&rd_h, &wr_h, sattr);704 %return windowsMakePipe(&rd_h, &wr_h, sattr);
705 %defer windowsDestroyPipe(rd_h, wr_h);
700 %return windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0);706 %return windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0);
701 *rd = rd_h;707 *rd = rd_h;
702 *wr = wr_h;708 *wr = wr_h;
703}709}
704710
705fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &windows.SECURITY_ATTRIBUTES) -> %void {711fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void {
706 var rd_h: windows.HANDLE = undefined;712 var rd_h: windows.HANDLE = undefined;
707 var wr_h: windows.HANDLE = undefined;713 var wr_h: windows.HANDLE = undefined;
708 %return windowsMakePipe(&rd_h, &wr_h, sattr);714 %return windowsMakePipe(&rd_h, &wr_h, sattr);
715 %defer windowsDestroyPipe(rd_h, wr_h);
709 %return windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0);716 %return windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0);
710 *rd = rd_h;717 *rd = rd_h;
711 *wr = wr_h;718 *wr = wr_h;
std/os/windows/index.zig+1-1
...@@ -18,7 +18,7 @@ pub extern "kernel32" stdcallcc fn CreateFileA(lpFileName: LPCSTR, dwDesiredAcce...@@ -18,7 +18,7 @@ pub extern "kernel32" stdcallcc fn CreateFileA(lpFileName: LPCSTR, dwDesiredAcce
18 dwFlagsAndAttributes: DWORD, hTemplateFile: ?HANDLE) -> HANDLE;18 dwFlagsAndAttributes: DWORD, hTemplateFile: ?HANDLE) -> HANDLE;
1919
20pub extern "kernel32" stdcallcc fn CreatePipe(hReadPipe: &HANDLE, hWritePipe: &HANDLE,20pub extern "kernel32" stdcallcc fn CreatePipe(hReadPipe: &HANDLE, hWritePipe: &HANDLE,
21 lpPipeAttributes: &SECURITY_ATTRIBUTES, nSize: DWORD) -> BOOL;21 lpPipeAttributes: &const SECURITY_ATTRIBUTES, nSize: DWORD) -> BOOL;
2222
23pub extern "kernel32" stdcallcc fn CreateProcessA(lpApplicationName: ?LPCSTR, lpCommandLine: LPSTR,23pub extern "kernel32" stdcallcc fn CreateProcessA(lpApplicationName: ?LPCSTR, lpCommandLine: LPSTR,
24 lpProcessAttributes: ?&SECURITY_ATTRIBUTES, lpThreadAttributes: ?&SECURITY_ATTRIBUTES, bInheritHandles: BOOL,24 lpProcessAttributes: ?&SECURITY_ATTRIBUTES, lpThreadAttributes: ?&SECURITY_ATTRIBUTES, bInheritHandles: BOOL,
test/tests.zig+6-8
...@@ -557,7 +557,7 @@ pub const CompileErrorContext = struct {...@@ -557,7 +557,7 @@ pub const CompileErrorContext = struct {
557 %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);557 %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
558558
559 if (b.verbose) {559 if (b.verbose) {
560 printInvocation(b.zig_exe, zig_args.toSliceConst());560 printInvocation(zig_args.toSliceConst());
561 }561 }
562562
563 const child = %%os.ChildProcess.init(zig_args.toSliceConst(), b.allocator);563 const child = %%os.ChildProcess.init(zig_args.toSliceConst(), b.allocator);
...@@ -625,10 +625,9 @@ pub const CompileErrorContext = struct {...@@ -625,10 +625,9 @@ pub const CompileErrorContext = struct {
625 }625 }
626 };626 };
627627
628 fn printInvocation(exe_path: []const u8, args: []const []const u8) {628 fn printInvocation(args: []const []const u8) {
629 %%io.stderr.printf("{}", exe_path);
630 for (args) |arg| {629 for (args) |arg| {
631 %%io.stderr.printf(" {}", arg);630 %%io.stderr.printf("{} ", arg);
632 }631 }
633 %%io.stderr.printf("\n");632 %%io.stderr.printf("\n");
634 }633 }
...@@ -826,7 +825,7 @@ pub const ParseCContext = struct {...@@ -826,7 +825,7 @@ pub const ParseCContext = struct {
826 %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);825 %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
827826
828 if (b.verbose) {827 if (b.verbose) {
829 printInvocation(b.zig_exe, zig_args.toSliceConst());828 printInvocation(zig_args.toSliceConst());
830 }829 }
831830
832 const child = %%os.ChildProcess.init(zig_args.toSliceConst(), b.allocator);831 const child = %%os.ChildProcess.init(zig_args.toSliceConst(), b.allocator);
...@@ -895,10 +894,9 @@ pub const ParseCContext = struct {...@@ -895,10 +894,9 @@ pub const ParseCContext = struct {
895 }894 }
896 };895 };
897896
898 fn printInvocation(exe_path: []const u8, args: []const []const u8) {897 fn printInvocation(args: []const []const u8) {
899 %%io.stderr.printf("{}", exe_path);
900 for (args) |arg| {898 for (args) |arg| {
901 %%io.stderr.printf(" {}", arg);899 %%io.stderr.printf("{} ", arg);
902 }900 }
903 %%io.stderr.printf("\n");901 %%io.stderr.printf("\n");
904 }902 }