diff options
| author | LemonBoy <thatlemon@gmail.com> | 2021-01-18 13:24:06 +0100 |
|---|---|---|
| committer | LemonBoy <thatlemon@gmail.com> | 2021-01-18 14:52:35 +0100 |
| commit | 9d18df142c2b1583fcf0d59982b571699a63223e (patch) | |
| tree | e728f42a2f7b21482267847141638b62fc3e1833 /lib/std/os.zig | |
| parent | 81183365852e7f871500a3f71810ae3b468f0027 (diff) | |
| download | zig-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.zig | 61 |
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{ |
