From 0d4f05bb8ad12e140b0f93157c3c3d2c87e2738c Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 23 Nov 2020 09:08:55 +0100 Subject: [PATCH] std: Remove O_NONBLOCK flag after locking We only need O_NONBLOCK when O_SHLOCK/O_EXLOCK are used and we don't want open() to block, don't let this bit leak to the user fd. --- lib/std/fs.zig | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 2419ea2a51..f927d53962 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -733,10 +733,10 @@ pub const Dir = struct { // (Or if it's darwin, as darwin's `open` doesn't support the O_SYNC flag) const has_flock_open_flags = @hasDecl(os, "O_EXLOCK") and !is_darwin; if (has_flock_open_flags) { - const nonblocking_lock_flag = if (flags.lock_nonblocking) + const nonblocking_lock_flag: u32 = if (flags.lock_nonblocking) os.O_NONBLOCK | os.O_SYNC else - @as(u32, 0); + 0; os_flags |= switch (flags.lock) { .None => @as(u32, 0), .Shared => os.O_SHLOCK | nonblocking_lock_flag, @@ -771,6 +771,22 @@ pub const Dir = struct { }); } + if (has_flock_open_flags and flags.lock_nonblocking) { + var fl_flags = os.fcntl(fd, os.F_GETFL, 0) catch |err| switch (err) { + error.FileBusy => unreachable, + error.Locked => unreachable, + error.PermissionDenied => unreachable, + else => |e| return e, + }; + fl_flags &= ~@as(usize, os.O_NONBLOCK); + _ = os.fcntl(fd, os.F_SETFL, fl_flags) catch |err| switch (err) { + error.FileBusy => unreachable, + error.Locked => unreachable, + error.PermissionDenied => unreachable, + else => |e| return e, + }; + } + return File{ .handle = fd, .capable_io_mode = .blocking, @@ -887,6 +903,22 @@ pub const Dir = struct { }); } + if (has_flock_open_flags and flags.lock_nonblocking) { + var fl_flags = os.fcntl(fd, os.F_GETFL, 0) catch |err| switch (err) { + error.FileBusy => unreachable, + error.Locked => unreachable, + error.PermissionDenied => unreachable, + else => |e| return e, + }; + fl_flags &= ~@as(usize, os.O_NONBLOCK); + _ = os.fcntl(fd, os.F_SETFL, fl_flags) catch |err| switch (err) { + error.FileBusy => unreachable, + error.Locked => unreachable, + error.PermissionDenied => unreachable, + else => |e| return e, + }; + } + return File{ .handle = fd, .capable_io_mode = .blocking,