Commit 73de620ad5

Jonathan Marler <johnnymarler@gmail.com>
2024-09-24 00:51:11
std.os.windows.ReadFile: handle ERROR_LOCK_VIOLATION
fixes #21500
1 parent e6fd01a
Changed files (4)
lib/std/fs/test.zig
@@ -1647,6 +1647,36 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" {
     try testing.expectError(error.WouldBlock, file2);
 }
 
+test "read from locked file" {
+    try testWithAllSupportedPathTypes(struct {
+        fn impl(ctx: *TestContext) !void {
+            const filename = try ctx.transformPath("read_lock_file_test.txt");
+
+            {
+                const f = try ctx.dir.createFile(filename, .{ .read = true });
+                defer f.close();
+                var buffer: [1]u8 = undefined;
+                _ = try f.readAll(&buffer);
+            }
+            {
+                const f = try ctx.dir.createFile(filename, .{
+                    .read = true,
+                    .lock = .exclusive,
+                });
+                defer f.close();
+                const f2 = try ctx.dir.openFile(filename, .{});
+                defer f2.close();
+                var buffer: [1]u8 = undefined;
+                if (builtin.os.tag == .windows) {
+                    try std.testing.expectError(error.LockViolation, f2.readAll(&buffer));
+                } else {
+                    try std.testing.expectEqual(0, f2.readAll(&buffer));
+                }
+            }
+        }
+    }.impl);
+}
+
 test "walker" {
     if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest;
 
lib/std/os/windows.zig
@@ -599,6 +599,8 @@ pub const ReadFileError = error{
     /// The specified network name is no longer available.
     ConnectionResetByPeer,
     OperationAborted,
+    /// Unable to read file due to lock.
+    LockViolation,
     Unexpected,
 };
 
@@ -630,6 +632,7 @@ pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64) ReadFileError!usiz
                 .BROKEN_PIPE => return 0,
                 .HANDLE_EOF => return 0,
                 .NETNAME_DELETED => return error.ConnectionResetByPeer,
+                .LOCK_VIOLATION => return error.LockViolation,
                 else => |err| return unexpectedError(err),
             }
         }
lib/std/zig/system.zig
@@ -1182,6 +1182,7 @@ fn preadAtLeast(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usi
             error.InputOutput => return error.FileSystem,
             error.AccessDenied => return error.Unexpected,
             error.ProcessNotFound => return error.ProcessNotFound,
+            error.LockViolation => return error.UnableToReadElfFile,
         };
         if (len == 0) return error.UnexpectedEndOfFile;
         i += len;
lib/std/posix.zig
@@ -802,6 +802,9 @@ pub const ReadError = error{
     /// This error occurs in Linux if the process to be read from
     /// no longer exists.
     ProcessNotFound,
+
+    /// Unable to read file due to lock.
+    LockViolation,
 } || UnexpectedError;
 
 /// Returns the number of bytes that were read, which can be less than