aboutsummaryrefslogtreecommitdiff
path: root/lib/std/os.zig
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2021-01-18 13:24:06 +0100
committerLemonBoy <thatlemon@gmail.com>2021-01-18 14:52:35 +0100
commit9d18df142c2b1583fcf0d59982b571699a63223e (patch)
treee728f42a2f7b21482267847141638b62fc3e1833 /lib/std/os.zig
parent81183365852e7f871500a3f71810ae3b468f0027 (diff)
downloadzig-9d18df142c2b1583fcf0d59982b571699a63223e.tar.gz
zig-9d18df142c2b1583fcf0d59982b571699a63223e.zip
std: Fixed pipe2 fallback
Use both F_SETFD and F_SETFL depending on what flag we're setting. Closes #7760
Diffstat (limited to 'lib/std/os.zig')
-rw-r--r--lib/std/os.zig61
1 files changed, 42 insertions, 19 deletions
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 4c8c51d5cc..f133ee4bdf 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -3755,31 +3755,54 @@ pub fn pipe() PipeError![2]fd_t {
}
pub fn pipe2(flags: u32) PipeError![2]fd_t {
- if (comptime std.Target.current.isDarwin()) {
- var fds: [2]fd_t = try pipe();
- if (flags == 0) return fds;
- errdefer {
- close(fds[0]);
- close(fds[1]);
- }
- for (fds) |fd| switch (errno(system.fcntl(fd, F_SETFL, flags))) {
- 0 => {},
+ if (@hasDecl(system, "pipe2")) {
+ var fds: [2]fd_t = undefined;
+ switch (errno(system.pipe2(&fds, flags))) {
+ 0 => return fds,
EINVAL => unreachable, // Invalid flags
- EBADF => unreachable, // Always a race condition
+ EFAULT => unreachable, // Invalid fds pointer
+ ENFILE => return error.SystemFdQuotaExceeded,
+ EMFILE => return error.ProcessFdQuotaExceeded,
else => |err| return unexpectedErrno(err),
- };
+ }
+ }
+
+ var fds: [2]fd_t = try pipe();
+ errdefer {
+ close(fds[0]);
+ close(fds[1]);
+ }
+
+ if (flags == 0)
return fds;
+
+ // O_CLOEXEC is special, it's a file descriptor flag and must be set using
+ // F_SETFD.
+ if (flags & O_CLOEXEC != 0) {
+ for (fds) |fd| {
+ switch (errno(system.fcntl(fd, F_SETFD, FD_CLOEXEC))) {
+ 0 => {},
+ EINVAL => unreachable, // Invalid flags
+ EBADF => unreachable, // Always a race condition
+ else => |err| return unexpectedErrno(err),
+ }
+ }
}
- var fds: [2]fd_t = undefined;
- switch (errno(system.pipe2(&fds, flags))) {
- 0 => return fds,
- EINVAL => unreachable, // Invalid flags
- EFAULT => unreachable, // Invalid fds pointer
- ENFILE => return error.SystemFdQuotaExceeded,
- EMFILE => return error.ProcessFdQuotaExceeded,
- else => |err| return unexpectedErrno(err),
+ const new_flags = flags & ~@as(u32, O_CLOEXEC);
+ // Set every other flag affecting the file status using F_SETFL.
+ if (new_flags != 0) {
+ for (fds) |fd| {
+ switch (errno(system.fcntl(fd, F_SETFL, new_flags))) {
+ 0 => {},
+ EINVAL => unreachable, // Invalid flags
+ EBADF => unreachable, // Always a race condition
+ else => |err| return unexpectedErrno(err),
+ }
+ }
}
+
+ return fds;
}
pub const SysCtlError = error{