Skip to content

Commit 7513ddb

Browse files
author
Jan Philipp Hafer
committed
adding probing, if inheritance is enabled + cleanups
1 parent b5c5a10 commit 7513ddb

File tree

4 files changed

+56
-54
lines changed

4 files changed

+56
-54
lines changed

lib/std/child_process.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1108,11 +1108,14 @@ pub const ChildProcess = struct {
11081108
}
11091109
};
11101110

1111+
/// Pipe read side
1112+
pub const pipe_rd = 0;
1113+
/// Pipe write side
1114+
pub const pipe_wr = 1;
11111115
const PortPipeT = if (builtin.os.tag == .windows) [2]windows.HANDLE else [2]os.fd_t;
11121116

11131117
/// Portable pipe creation with disabled inheritance
11141118
pub inline fn portablePipe() !PortPipeT {
1115-
// TODO think how to offer user an interface to lpSecurityDescriptor
11161119
var pipe_new: PortPipeT = undefined;
11171120
if (builtin.os.tag == .windows) {
11181121
const saAttr = windows.SECURITY_ATTRIBUTES{

lib/std/os.zig

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -44,32 +44,6 @@ 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-
/// Pipe read side
48-
pub const pipe_rd = 0;
49-
/// Pipe write side
50-
pub const pipe_wr = 1;
51-
52-
pub const windowsPtrDigits: usize = std.math.log10(math.maxInt(usize));
53-
pub const otherPtrDigits: usize = std.math.log10(math.maxInt(u32)) + 1; // +1 for sign
54-
pub const handleCharSize = if (builtin.target.os.tag == .windows) windowsPtrDigits else otherPtrDigits;
55-
56-
pub fn handleToString(handle: fd_t, buf: []u8) std.fmt.BufPrintError![]u8 {
57-
var s_handle: []u8 = undefined;
58-
const handle_int =
59-
// handle is *anyopaque or an integer on unix-likes Kernels.
60-
if (builtin.target.os.tag == .windows) @ptrToInt(handle) else handle;
61-
s_handle = try std.fmt.bufPrint(buf[0..], "{d}", .{handle_int});
62-
return s_handle;
63-
}
64-
65-
pub fn stringToHandle(s_handle: []const u8) std.fmt.ParseIntError!std.os.fd_t {
66-
var file_handle: std.os.fd_t = if (builtin.target.os.tag == .windows)
67-
@intToPtr(windows.HANDLE, try std.fmt.parseInt(usize, s_handle, 10))
68-
else
69-
try std.fmt.parseInt(std.os.fd_t, s_handle, 10);
70-
return file_handle;
71-
}
72-
7347
comptime {
7448
assert(@import("std") == std); // std lib tests require --zig-lib-dir
7549
}
@@ -314,6 +288,27 @@ pub fn close(fd: fd_t) void {
314288
}
315289
}
316290

291+
pub const windowsPtrDigits = 19; // log10(max(usize))
292+
pub const unixoidPtrDigits = 10; // log10(max(u32)) + 1 for sign
293+
pub const handleCharSize = if (builtin.target.os.tag == .windows) windowsPtrDigits else unixoidPtrDigits;
294+
295+
pub fn handleToString(handle: fd_t, buf: []u8) std.fmt.BufPrintError![]u8 {
296+
var s_handle: []u8 = undefined;
297+
const handle_int =
298+
// handle is *anyopaque or an integer on unix-likes Kernels.
299+
if (builtin.target.os.tag == .windows) @ptrToInt(handle) else handle;
300+
s_handle = try std.fmt.bufPrint(buf[0..], "{d}", .{handle_int});
301+
return s_handle;
302+
}
303+
304+
pub fn stringToHandle(s_handle: []const u8) std.fmt.ParseIntError!std.os.fd_t {
305+
var handle: std.os.fd_t = if (builtin.target.os.tag == .windows)
306+
@intToPtr(windows.HANDLE, try std.fmt.parseInt(usize, s_handle, 10))
307+
else
308+
try std.fmt.parseInt(std.os.fd_t, s_handle, 10);
309+
return handle;
310+
}
311+
317312
pub const FChmodError = error{
318313
AccessDenied,
319314
InputOutput,
@@ -4869,25 +4864,41 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
48694864
}
48704865
}
48714866

4867+
const IsInheritableError = FcntlError || windows.GetHandleInformationError;
4868+
4869+
/// Whether inheritence is enabled or CLOEXEC is not set.
4870+
pub inline fn isInheritable(handle: fd_t) IsInheritableError!bool {
4871+
if (builtin.os.tag == .windows) {
4872+
var handle_flags: windows.DWORD = undefined;
4873+
try windows.GetHandleInformation(handle, &handle_flags);
4874+
return handle_flags & windows.HANDLE_FLAG_INHERIT != 0;
4875+
} else {
4876+
const fcntl_flags = try fcntl(handle, F.GETFD, 0);
4877+
return fcntl_flags & FD_CLOEXEC == 0;
4878+
}
4879+
}
4880+
48724881
const EnableInheritanceError = FcntlError || windows.SetHandleInformationError;
48734882

4874-
pub inline fn enableInheritance(file_handle: fd_t) EnableInheritanceError!void {
4883+
/// Enables inheritence or sets CLOEXEC.
4884+
pub inline fn enableInheritance(handle: fd_t) EnableInheritanceError!void {
48754885
if (builtin.os.tag == .windows) {
4876-
try windows.SetHandleInformation(file_handle, windows.HANDLE_FLAG_INHERIT, 1);
4886+
try windows.SetHandleInformation(handle, windows.HANDLE_FLAG_INHERIT, 1);
48774887
} else {
4878-
var flags = try fcntl(file_handle, F.GETFD, 0);
4888+
var flags = try fcntl(handle, F.GETFD, 0);
48794889
flags &= ~@as(u32, FD_CLOEXEC);
4880-
_ = try fcntl(file_handle, F.SETFD, flags);
4890+
_ = try fcntl(handle, F.SETFD, flags);
48814891
}
48824892
}
48834893

48844894
const DisableInheritanceError = FcntlError || windows.SetHandleInformationError;
48854895

4886-
pub inline fn disableInheritance(file_handle: fd_t) DisableInheritanceError!void {
4896+
/// Disables inheritence or unsets CLOEXEC.
4897+
pub inline fn disableInheritance(handle: fd_t) DisableInheritanceError!void {
48874898
if (builtin.os.tag == .windows) {
4888-
try windows.SetHandleInformation(file_handle, windows.HANDLE_FLAG_INHERIT, 0);
4899+
try windows.SetHandleInformation(handle, windows.HANDLE_FLAG_INHERIT, 0);
48894900
} else {
4890-
_ = try fcntl(file_handle, F.SETFD, FD_CLOEXEC);
4901+
_ = try fcntl(handle, F.SETFD, FD_CLOEXEC);
48914902
}
48924903
}
48934904

test/standalone/childprocess_extrapipe/child.zig

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,10 @@ pub fn main() !void {
1212
const s_handle = it.next() orelse unreachable;
1313
var file_handle = try std.os.stringToHandle(s_handle);
1414

15-
if (builtin.target.os.tag == .windows) {
16-
// windows.HANDLE_FLAG_INHERIT is enabled
17-
var handle_flags: windows.DWORD = undefined;
18-
try windows.GetHandleInformation(file_handle, &handle_flags);
19-
try std.testing.expect(handle_flags & windows.HANDLE_FLAG_INHERIT != 0);
20-
} else {
21-
// FD_CLOEXEC is not set
22-
var fcntl_flags = try std.os.fcntl(file_handle, std.os.F.GETFD, 0);
23-
try std.testing.expect((fcntl_flags & std.os.FD_CLOEXEC) == 0);
24-
}
15+
// child inherited the handle, so inheritance must be enabled
16+
const is_inheritable = try std.os.isInheritable(file_handle);
17+
std.debug.assert(is_inheritable);
18+
2519
try std.os.disableInheritance(file_handle);
2620
var file_in = std.fs.File{ .handle = file_handle }; // read side of pipe
2721
defer file_in.close();

test/standalone/childprocess_extrapipe/parent.zig

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +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-
const pipe_rd = os.pipe_rd;
10-
const pipe_wr = os.pipe_wr;
9+
const pipe_rd = child_process.pipe_rd;
10+
const pipe_wr = child_process.pipe_wr;
1111

1212
pub fn main() !void {
1313
var gpa_state = std.heap.GeneralPurposeAllocator(.{}){};
@@ -39,14 +39,8 @@ pub fn main() !void {
3939
}
4040

4141
// check that inheritance was disabled for the handle the whole time
42-
if (builtin.target.os.tag == .windows) {
43-
var handle_flags: windows.DWORD = undefined;
44-
try windows.GetHandleInformation(pipe[pipe_wr], &handle_flags);
45-
std.debug.assert(handle_flags & windows.HANDLE_FLAG_INHERIT == 0);
46-
} else {
47-
const fcntl_flags = try os.fcntl(pipe[pipe_wr], os.F.GETFD, 0);
48-
try std.testing.expect((fcntl_flags & os.FD_CLOEXEC) != 0);
49-
}
42+
const is_inheritable = try os.isInheritable(pipe[pipe_wr]);
43+
std.debug.assert(!is_inheritable);
5044

5145
var file_out = std.fs.File{ .handle = pipe[pipe_wr] };
5246
defer file_out.close();

0 commit comments

Comments
 (0)