From 8ccb9a6ad327a4d7fbc321b33d4aa66a27a1f5ee Mon Sep 17 00:00:00 2001 From: Casey Banner Date: Tue, 6 Dec 2022 23:15:54 -0500 Subject: cache: Fix LockViolation during C compilation paths (#13591) - C compilation flows didn't hold an exclusive lock on the cache manifest file when writing to it in all cases - On windows, explicitly unlock the file lock before closing it --- src/Cache.zig | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src/Cache.zig') diff --git a/src/Cache.zig b/src/Cache.zig index a645e06594..586979c187 100644 --- a/src/Cache.zig +++ b/src/Cache.zig @@ -232,6 +232,12 @@ pub const Lock = struct { manifest_file: fs.File, pub fn release(lock: *Lock) void { + if (builtin.os.tag == .windows) { + // Windows does not guarantee that locks are immediately unlocked when + // the file handle is closed. See LockFileEx documentation. + lock.manifest_file.unlock(); + } + lock.manifest_file.close(); lock.* = undefined; } @@ -554,7 +560,10 @@ pub const Manifest = struct { return false; } - try self.downgradeToSharedLock(); + if (self.want_shared_lock) { + try self.downgradeToSharedLock(); + } + return true; } @@ -866,11 +875,13 @@ pub const Manifest = struct { const manifest_file = self.manifest_file.?; try manifest_file.downgradeLock(); } + self.have_exclusive_lock = false; } fn upgradeToExclusiveLock(self: *Manifest) !void { if (self.have_exclusive_lock) return; + assert(self.manifest_file != null); // WASI does not currently support flock, so we bypass it here. // TODO: If/when flock is supported on WASI, this check should be removed. @@ -892,6 +903,7 @@ pub const Manifest = struct { const lock: Lock = .{ .manifest_file = self.manifest_file.?, }; + self.manifest_file = null; return lock; } @@ -901,6 +913,11 @@ pub const Manifest = struct { /// Don't forget to call `writeManifest` before this! pub fn deinit(self: *Manifest) void { if (self.manifest_file) |file| { + if (builtin.os.tag == .windows) { + // See Lock.release for why this is required on Windows + file.unlock(); + } + file.close(); } for (self.files.items) |*file| { -- cgit v1.2.3