Commit 0d4f05bb8a

LemonBoy <thatlemon@gmail.com>
2020-11-23 09:08:55
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.
1 parent f8ddc3d
Changed files (1)
lib
std
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,