Skip to content

Commit bb169a7

Browse files
committed
fix child process stdio piping behavior on windows
1 parent 1fe1e6e commit bb169a7

4 files changed

Lines changed: 22 additions & 17 deletions

File tree

std/io.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,8 @@ pub const InStream = struct {
313313
else => error.Unexpected,
314314
};
315315
}
316-
if (amt_read == 0) return index;
317316
index += amt_read;
317+
if (amt_read < want_read_count) return index;
318318
}
319319
return index;
320320
} else {

std/os/child_process.zig

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ pub const ChildProcess = struct {
433433
}
434434

435435
fn spawnWindows(self: &ChildProcess) -> %void {
436-
var saAttr = windows.SECURITY_ATTRIBUTES {
436+
const saAttr = windows.SECURITY_ATTRIBUTES {
437437
.nLength = @sizeOf(windows.SECURITY_ATTRIBUTES),
438438
.bInheritHandle = windows.TRUE,
439439
.lpSecurityDescriptor = null,
@@ -459,7 +459,7 @@ pub const ChildProcess = struct {
459459
var g_hChildStd_IN_Wr: ?windows.HANDLE = null;
460460
switch (self.stdin_behavior) {
461461
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);
463463
},
464464
StdIo.Ignore => {
465465
g_hChildStd_IN_Rd = nul_handle;
@@ -477,7 +477,7 @@ pub const ChildProcess = struct {
477477
var g_hChildStd_OUT_Wr: ?windows.HANDLE = null;
478478
switch (self.stdout_behavior) {
479479
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);
481481
},
482482
StdIo.Ignore => {
483483
g_hChildStd_OUT_Wr = nul_handle;
@@ -495,7 +495,7 @@ pub const ChildProcess = struct {
495495
var g_hChildStd_ERR_Wr: ?windows.HANDLE = null;
496496
switch (self.stderr_behavior) {
497497
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);
499499
},
500500
StdIo.Ignore => {
501501
g_hChildStd_ERR_Wr = nul_handle;
@@ -675,7 +675,12 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) {
675675
if (wr) |h| os.windowsClose(h);
676676
}
677677

678-
fn 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
681+
const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES;
682+
683+
fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void {
679684
if (windows.CreatePipe(rd, wr, sattr, 0) == 0) {
680685
const err = windows.GetLastError();
681686
return switch (err) {
@@ -693,19 +698,21 @@ fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.D
693698
}
694699
}
695700

696-
fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &windows.SECURITY_ATTRIBUTES) -> %void {
701+
fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void {
697702
var rd_h: windows.HANDLE = undefined;
698703
var wr_h: windows.HANDLE = undefined;
699704
%return windowsMakePipe(&rd_h, &wr_h, sattr);
705+
%defer windowsDestroyPipe(rd_h, wr_h);
700706
%return windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0);
701707
*rd = rd_h;
702708
*wr = wr_h;
703709
}
704710

705-
fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &windows.SECURITY_ATTRIBUTES) -> %void {
711+
fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void {
706712
var rd_h: windows.HANDLE = undefined;
707713
var wr_h: windows.HANDLE = undefined;
708714
%return windowsMakePipe(&rd_h, &wr_h, sattr);
715+
%defer windowsDestroyPipe(rd_h, wr_h);
709716
%return windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0);
710717
*rd = rd_h;
711718
*wr = wr_h;

std/os/windows/index.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub extern "kernel32" stdcallcc fn CreateFileA(lpFileName: LPCSTR, dwDesiredAcce
1818
dwFlagsAndAttributes: DWORD, hTemplateFile: ?HANDLE) -> HANDLE;
1919

2020
pub 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

2323
pub extern "kernel32" stdcallcc fn CreateProcessA(lpApplicationName: ?LPCSTR, lpCommandLine: LPSTR,
2424
lpProcessAttributes: ?&SECURITY_ATTRIBUTES, lpThreadAttributes: ?&SECURITY_ATTRIBUTES, bInheritHandles: BOOL,

test/tests.zig

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ pub const CompileErrorContext = struct {
557557
%%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
558558

559559
if (b.verbose) {
560-
printInvocation(b.zig_exe, zig_args.toSliceConst());
560+
printInvocation(zig_args.toSliceConst());
561561
}
562562

563563
const child = %%os.ChildProcess.init(zig_args.toSliceConst(), b.allocator);
@@ -625,10 +625,9 @@ pub const CompileErrorContext = struct {
625625
}
626626
};
627627

628-
fn printInvocation(exe_path: []const u8, args: []const []const u8) {
629-
%%io.stderr.printf("{}", exe_path);
628+
fn printInvocation(args: []const []const u8) {
630629
for (args) |arg| {
631-
%%io.stderr.printf(" {}", arg);
630+
%%io.stderr.printf("{} ", arg);
632631
}
633632
%%io.stderr.printf("\n");
634633
}
@@ -826,7 +825,7 @@ pub const ParseCContext = struct {
826825
%%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
827826

828827
if (b.verbose) {
829-
printInvocation(b.zig_exe, zig_args.toSliceConst());
828+
printInvocation(zig_args.toSliceConst());
830829
}
831830

832831
const child = %%os.ChildProcess.init(zig_args.toSliceConst(), b.allocator);
@@ -895,10 +894,9 @@ pub const ParseCContext = struct {
895894
}
896895
};
897896

898-
fn printInvocation(exe_path: []const u8, args: []const []const u8) {
899-
%%io.stderr.printf("{}", exe_path);
897+
fn printInvocation(args: []const []const u8) {
900898
for (args) |arg| {
901-
%%io.stderr.printf(" {}", arg);
899+
%%io.stderr.printf("{} ", arg);
902900
}
903901
%%io.stderr.printf("\n");
904902
}

0 commit comments

Comments
 (0)