Skip to content

Commit 7324b06

Browse files
committed
helper methods to make more nice for the user
1 parent b89b498 commit 7324b06

File tree

3 files changed

+39
-30
lines changed

3 files changed

+39
-30
lines changed

lib/std/os.zig

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,33 @@ pub const windows = @import("os/windows.zig");
4444
pub const posix_spawn = @import("os/posix_spawn.zig");
4545
pub const ptrace = @import("os/ptrace.zig");
4646

47-
// TODO where should we add our own target infos for things that we have bindings for?
47+
// Zig support for posix spawn on the platform
4848
pub const hasPosixSpawn = builtin.target.isDarwin();
49+
/// Pipe read side
50+
pub const pipe_rd = 0;
51+
/// Pipe write side
52+
pub const pipe_wr = 1;
53+
54+
pub const windowsPtrDigits: usize = std.math.log10(math.maxInt(usize));
55+
pub const otherPtrDigits: usize = std.math.log10(math.maxInt(u32)) + 1; // +1 for sign
56+
pub const handleCharSize = if (builtin.target.os.tag == .windows) windowsPtrDigits else otherPtrDigits;
57+
58+
pub fn handleToString(handle: fd_t, buf: []u8) std.fmt.BufPrintError![]u8 {
59+
var s_handle: []u8 = undefined;
60+
const handle_int =
61+
// handle is *anyopaque or an integer on unix-likes Kernels.
62+
if (builtin.target.os.tag == .windows) @ptrToInt(handle) else handle;
63+
s_handle = try std.fmt.bufPrint(buf[0..], "{d}", .{handle_int});
64+
return s_handle;
65+
}
66+
67+
pub fn stringToHandle(s_handle: []const u8) std.fmt.ParseIntError!std.os.fd_t {
68+
var file_handle: std.os.fd_t = if (builtin.target.os.tag == .windows)
69+
@intToPtr(windows.HANDLE, try std.fmt.parseInt(usize, s_handle, 10))
70+
else
71+
try std.fmt.parseInt(std.os.fd_t, s_handle, 10);
72+
return file_handle;
73+
}
4974

5075
comptime {
5176
assert(@import("std") == std); // std lib tests require --zig-lib-dir

test/standalone/childprocess_extrapipe/child.zig

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@ pub fn main() !void {
1010
defer it.deinit();
1111
_ = it.next() orelse unreachable; // skip binary name
1212
const s_handle = it.next() orelse unreachable;
13-
14-
var file_handle: std.os.fd_t = if (builtin.target.os.tag == .windows)
15-
@intToPtr(windows.HANDLE, try std.fmt.parseInt(usize, s_handle, 10))
16-
else
17-
try std.fmt.parseInt(std.os.fd_t, s_handle, 10);
13+
var file_handle = try std.os.stringToHandle(s_handle);
1814
// TODO: Is there a way on Windows to let the Kernel disable inheritance
1915
// after it is inherited in CreateProcess???
2016
if (builtin.target.os.tag == .windows) {

test/standalone/childprocess_extrapipe/parent.zig

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,8 @@ const windows = std.os.windows;
66
const os = std.os;
77
const testing = std.testing;
88
const child_process = std.child_process;
9-
10-
const windowsPtrDigits: usize = std.math.log10(math.maxInt(usize));
11-
const otherPtrDigits: usize = std.math.log10(math.maxInt(u32)) + 1; // +1 for sign
12-
const handleCharSize = if (builtin.target.os.tag == .windows) windowsPtrDigits else otherPtrDigits;
13-
14-
/// assert: buf can store the handle
15-
fn handleToString(handle: os.fd_t, buf: []u8) std.fmt.BufPrintError![]u8 {
16-
var s_handle: []u8 = undefined;
17-
const handle_int =
18-
// handle is *anyopaque or an integer on unix-likes Kernels.
19-
if (builtin.target.os.tag == .windows) @ptrToInt(handle) else handle;
20-
s_handle = try std.fmt.bufPrint(buf[0..], "{d}", .{handle_int});
21-
return s_handle;
22-
}
9+
const pipe_rd = os.pipe_rd;
10+
const pipe_wr = os.pipe_wr;
2311

2412
pub fn main() !void {
2513
var gpa_state = std.heap.GeneralPurposeAllocator(.{}){};
@@ -40,44 +28,44 @@ pub fn main() !void {
4028
.lpSecurityDescriptor = null,
4129
};
4230
// create pipe and enable inheritance for the read end, which will be given to the child
43-
try child_process.windowsMakeAsyncPipe(&pipe[0], &pipe[1], &saAttr, .parent_to_child);
31+
try child_process.windowsMakeAsyncPipe(&pipe[pipe_rd], &pipe[pipe_wr], &saAttr, .parent_to_child);
4432
} else {
4533
pipe = try os.pipe(); // leaks on default, but more portable, TODO: use pip2 and close earlier?
4634
}
4735

4836
// write read side of pipe to string + add to spawn command
49-
var buf: [handleCharSize]u8 = comptime [_]u8{0} ** handleCharSize;
50-
const s_handle = try handleToString(pipe[0], &buf);
37+
var buf: [os.handleCharSize]u8 = comptime [_]u8{0} ** os.handleCharSize;
38+
const s_handle = try os.handleToString(pipe[pipe_rd], &buf);
5139
var child_proc = ChildProcess.init(
5240
&.{ child_path, s_handle },
5341
gpa,
5442
);
5543
{
56-
// close read side of pipe, less time for leaking, if closed immediately
44+
// close read side of pipe, less time for leaking, if closed immediately with posix_spawn
5745
if (os.hasPosixSpawn) child_proc.posix_actions = try os.posix_spawn.Actions.init();
5846
defer if (os.hasPosixSpawn) child_proc.posix_actions.?.deinit();
59-
if (os.hasPosixSpawn) try child_proc.posix_actions.?.close(pipe[1]); // TODO: This is not closed in child
60-
defer os.close(pipe[0]);
47+
if (os.hasPosixSpawn) try child_proc.posix_actions.?.close(pipe[pipe_wr]);
48+
defer os.close(pipe[pipe_rd]);
6149

6250
try child_proc.spawn();
6351
}
6452

6553
// call fcntl on Unixes to disable handle inheritance (windows one is per default not enabled)
6654
if (builtin.os.tag != .windows) {
67-
try std.os.disableFileInheritance(pipe[1]);
55+
try std.os.disableFileInheritance(pipe[pipe_wr]);
6856
}
6957

7058
// windows does have inheritance disabled on default, but we check to be sure
7159
if (builtin.target.os.tag == .windows) {
7260
var handle_flags: windows.DWORD = undefined;
73-
try windows.GetHandleInformation(pipe[1].?, &handle_flags);
61+
try windows.GetHandleInformation(pipe[pipe_wr], &handle_flags);
7462
std.debug.assert(handle_flags & windows.HANDLE_FLAG_INHERIT == 0);
7563
} else {
76-
const fcntl_flags = try os.fcntl(pipe[1], os.F.GETFD, 0);
64+
const fcntl_flags = try os.fcntl(pipe[pipe_wr], os.F.GETFD, 0);
7765
try std.testing.expect((fcntl_flags & os.FD_CLOEXEC) != 0);
7866
}
7967

80-
var file_out = std.fs.File{ .handle = pipe[1] };
68+
var file_out = std.fs.File{ .handle = pipe[pipe_wr] };
8169
defer file_out.close();
8270
const file_out_writer = file_out.writer();
8371
try file_out_writer.writeAll("test123\x17"); // ETB = \x17

0 commit comments

Comments
 (0)