Skip to content

Commit

Permalink
fix child process stdio piping behavior on windows
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrk committed Oct 15, 2017
1 parent 1fe1e6e commit bb169a7
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 17 deletions.
2 changes: 1 addition & 1 deletion std/io.zig
Expand Up @@ -313,8 +313,8 @@ pub const InStream = struct {
else => error.Unexpected,
};
}
if (amt_read == 0) return index;
index += amt_read;
if (amt_read < want_read_count) return index;
}
return index;
} else {
Expand Down
21 changes: 14 additions & 7 deletions std/os/child_process.zig
Expand Up @@ -433,7 +433,7 @@ pub const ChildProcess = struct {
}

fn spawnWindows(self: &ChildProcess) -> %void {
var saAttr = windows.SECURITY_ATTRIBUTES {
const saAttr = windows.SECURITY_ATTRIBUTES {
.nLength = @sizeOf(windows.SECURITY_ATTRIBUTES),
.bInheritHandle = windows.TRUE,
.lpSecurityDescriptor = null,
Expand All @@ -459,7 +459,7 @@ pub const ChildProcess = struct {
var g_hChildStd_IN_Wr: ?windows.HANDLE = null;
switch (self.stdin_behavior) {
StdIo.Pipe => {
%return windowsMakePipeIn(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr);
%return windowsMakePipeIn(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, saAttr);
},
StdIo.Ignore => {
g_hChildStd_IN_Rd = nul_handle;
Expand All @@ -477,7 +477,7 @@ pub const ChildProcess = struct {
var g_hChildStd_OUT_Wr: ?windows.HANDLE = null;
switch (self.stdout_behavior) {
StdIo.Pipe => {
%return windowsMakePipeOut(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr);
%return windowsMakePipeOut(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, saAttr);
},
StdIo.Ignore => {
g_hChildStd_OUT_Wr = nul_handle;
Expand All @@ -495,7 +495,7 @@ pub const ChildProcess = struct {
var g_hChildStd_ERR_Wr: ?windows.HANDLE = null;
switch (self.stderr_behavior) {
StdIo.Pipe => {
%return windowsMakePipeOut(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr);
%return windowsMakePipeOut(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, saAttr);
},
StdIo.Ignore => {
g_hChildStd_ERR_Wr = nul_handle;
Expand Down Expand Up @@ -675,7 +675,12 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) {
if (wr) |h| os.windowsClose(h);
}

fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &windows.SECURITY_ATTRIBUTES) -> %void {

// TODO: workaround for bug where the `const` from `&const` is dropped when the type is
// a namespace field lookup
const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES;

fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void {
if (windows.CreatePipe(rd, wr, sattr, 0) == 0) {
const err = windows.GetLastError();
return switch (err) {
Expand All @@ -693,19 +698,21 @@ fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.D
}
}

fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &windows.SECURITY_ATTRIBUTES) -> %void {
fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void {
var rd_h: windows.HANDLE = undefined;
var wr_h: windows.HANDLE = undefined;
%return windowsMakePipe(&rd_h, &wr_h, sattr);
%defer windowsDestroyPipe(rd_h, wr_h);
%return windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0);
*rd = rd_h;
*wr = wr_h;
}

fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &windows.SECURITY_ATTRIBUTES) -> %void {
fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void {
var rd_h: windows.HANDLE = undefined;
var wr_h: windows.HANDLE = undefined;
%return windowsMakePipe(&rd_h, &wr_h, sattr);
%defer windowsDestroyPipe(rd_h, wr_h);
%return windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0);
*rd = rd_h;
*wr = wr_h;
Expand Down
2 changes: 1 addition & 1 deletion std/os/windows/index.zig
Expand Up @@ -18,7 +18,7 @@ pub extern "kernel32" stdcallcc fn CreateFileA(lpFileName: LPCSTR, dwDesiredAcce
dwFlagsAndAttributes: DWORD, hTemplateFile: ?HANDLE) -> HANDLE;

pub extern "kernel32" stdcallcc fn CreatePipe(hReadPipe: &HANDLE, hWritePipe: &HANDLE,
lpPipeAttributes: &SECURITY_ATTRIBUTES, nSize: DWORD) -> BOOL;
lpPipeAttributes: &const SECURITY_ATTRIBUTES, nSize: DWORD) -> BOOL;

pub extern "kernel32" stdcallcc fn CreateProcessA(lpApplicationName: ?LPCSTR, lpCommandLine: LPSTR,
lpProcessAttributes: ?&SECURITY_ATTRIBUTES, lpThreadAttributes: ?&SECURITY_ATTRIBUTES, bInheritHandles: BOOL,
Expand Down
14 changes: 6 additions & 8 deletions test/tests.zig
Expand Up @@ -557,7 +557,7 @@ pub const CompileErrorContext = struct {
%%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);

if (b.verbose) {
printInvocation(b.zig_exe, zig_args.toSliceConst());
printInvocation(zig_args.toSliceConst());
}

const child = %%os.ChildProcess.init(zig_args.toSliceConst(), b.allocator);
Expand Down Expand Up @@ -625,10 +625,9 @@ pub const CompileErrorContext = struct {
}
};

fn printInvocation(exe_path: []const u8, args: []const []const u8) {
%%io.stderr.printf("{}", exe_path);
fn printInvocation(args: []const []const u8) {
for (args) |arg| {
%%io.stderr.printf(" {}", arg);
%%io.stderr.printf("{} ", arg);
}
%%io.stderr.printf("\n");
}
Expand Down Expand Up @@ -826,7 +825,7 @@ pub const ParseCContext = struct {
%%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);

if (b.verbose) {
printInvocation(b.zig_exe, zig_args.toSliceConst());
printInvocation(zig_args.toSliceConst());
}

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

fn printInvocation(exe_path: []const u8, args: []const []const u8) {
%%io.stderr.printf("{}", exe_path);
fn printInvocation(args: []const []const u8) {
for (args) |arg| {
%%io.stderr.printf(" {}", arg);
%%io.stderr.printf("{} ", arg);
}
%%io.stderr.printf("\n");
}
Expand Down

0 comments on commit bb169a7

Please sign in to comment.