diff --git a/src/Cache.zig b/src/Cache.zig index 850a28b42e..f0248a231b 100644 --- a/src/Cache.zig +++ b/src/Cache.zig @@ -735,6 +735,8 @@ pub const Manifest = struct { /// If `want_shared_lock` is true, this function automatically downgrades the /// lock from exclusive to shared. pub fn writeManifest(self: *Manifest) !void { + assert(self.have_exclusive_lock); + const manifest_file = self.manifest_file.?; if (self.manifest_dirty) { self.manifest_dirty = false; @@ -936,7 +938,7 @@ test "cache file and then recall it" { try testing.expect(try ch.hit()); digest2 = ch.final(); - try ch.writeManifest(); + try testing.expectEqual(false, ch.have_exclusive_lock); } try testing.expectEqual(digest1, digest2); @@ -1062,7 +1064,7 @@ test "no file inputs" { try testing.expect(try man.hit()); digest2 = man.final(); - try man.writeManifest(); + try testing.expectEqual(false, man.have_exclusive_lock); } try testing.expectEqual(digest1, digest2); @@ -1124,7 +1126,7 @@ test "Manifest with files added after initial hash work" { try testing.expect(try ch.hit()); digest2 = ch.final(); - try ch.writeManifest(); + try testing.expectEqual(false, ch.have_exclusive_lock); } try testing.expect(mem.eql(u8, &digest1, &digest2)); diff --git a/src/Compilation.zig b/src/Compilation.zig index 9ba2f77311..3ddf936e57 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3693,13 +3693,15 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { break :digest digest; } else man.final(); - // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is - // possible we had a hit and the manifest is dirty, for example if the file mtime changed but - // the contents were the same, we hit the cache but the manifest is dirty and we need to update - // it to prevent doing a full file content comparison the next time around. - man.writeManifest() catch |err| { - log.warn("failed to write cache manifest for C import: {s}", .{@errorName(err)}); - }; + if (man.have_exclusive_lock) { + // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is + // possible we had a hit and the manifest is dirty, for example if the file mtime changed but + // the contents were the same, we hit the cache but the manifest is dirty and we need to update + // it to prevent doing a full file content comparison the next time around. + man.writeManifest() catch |err| { + log.warn("failed to write cache manifest for C import: {s}", .{@errorName(err)}); + }; + } const out_zig_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{ "o", &digest, cimport_zig_basename, @@ -4160,13 +4162,15 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P break :blk digest; }; - // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is - // possible we had a hit and the manifest is dirty, for example if the file mtime changed but - // the contents were the same, we hit the cache but the manifest is dirty and we need to update - // it to prevent doing a full file content comparison the next time around. - man.writeManifest() catch |err| { - log.warn("failed to write cache manifest when compiling '{s}': {s}", .{ c_object.src.src_path, @errorName(err) }); - }; + if (man.have_exclusive_lock) { + // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is + // possible we had a hit and the manifest is dirty, for example if the file mtime changed but + // the contents were the same, we hit the cache but the manifest is dirty and we need to update + // it to prevent doing a full file content comparison the next time around. + man.writeManifest() catch |err| { + log.warn("failed to write cache manifest when compiling '{s}': {s}", .{ c_object.src.src_path, @errorName(err) }); + }; + } const o_basename = try std.fmt.allocPrint(arena, "{s}{s}", .{ o_basename_noext, o_ext });