| ... | @@ -12,15 +12,6 @@ const mem = std.mem; | ... | @@ -12,15 +12,6 @@ const mem = std.mem; |
| 12 | const fmt = std.fmt; | 12 | const fmt = std.fmt; |
| 13 | const Allocator = std.mem.Allocator; | 13 | const Allocator = std.mem.Allocator; |
| 14 | | 14 | |
| 15 | /// Process-scoped map keeping track of all locked Cache hashes, to detect deadlocks. | | |
| 16 | /// This protection is conditionally compiled depending on `want_debug_deadlock`. | | |
| 17 | var all_cache_digest_set: std.AutoHashMapUnmanaged(BinDigest, void) = .{}; | | |
| 18 | var all_cache_digest_lock: std.Mutex = .{}; | | |
| 19 | var all_cache_digest_allocator: ?*Allocator = null; | | |
| 20 | const want_debug_deadlock = std.debug.runtime_safety; | | |
| 21 | const DebugBinDigest = if (want_debug_deadlock) BinDigest else void; | | |
| 22 | const null_debug_bin_digest = if (want_debug_deadlock) ([1]u8{0} ** bin_digest_len) else {}; | | |
| 23 | | | |
| 24 | /// Be sure to call `Manifest.deinit` after successful initialization. | 15 | /// Be sure to call `Manifest.deinit` after successful initialization. |
| 25 | pub fn obtain(cache: *const Cache) Manifest { | 16 | pub fn obtain(cache: *const Cache) Manifest { |
| 26 | return Manifest{ | 17 | return Manifest{ |
| ... | @@ -169,15 +160,8 @@ pub const HashHelper = struct { | ... | @@ -169,15 +160,8 @@ pub const HashHelper = struct { |
| 169 | | 160 | |
| 170 | pub const Lock = struct { | 161 | pub const Lock = struct { |
| 171 | manifest_file: fs.File, | 162 | manifest_file: fs.File, |
| 172 | debug_bin_digest: DebugBinDigest, | | |
| 173 | | 163 | |
| 174 | pub fn release(lock: *Lock) void { | 164 | pub fn release(lock: *Lock) void { |
| 175 | if (want_debug_deadlock) { | | |
| 176 | const held = all_cache_digest_lock.acquire(); | | |
| 177 | defer held.release(); | | |
| 178 | | | |
| 179 | all_cache_digest_set.removeAssertDiscard(lock.debug_bin_digest); | | |
| 180 | } | | |
| 181 | lock.manifest_file.close(); | 165 | lock.manifest_file.close(); |
| 182 | lock.* = undefined; | 166 | lock.* = undefined; |
| 183 | } | 167 | } |
| ... | @@ -194,7 +178,6 @@ pub const Manifest = struct { | ... | @@ -194,7 +178,6 @@ pub const Manifest = struct { |
| 194 | manifest_dirty: bool, | 178 | manifest_dirty: bool, |
| 195 | files: std.ArrayListUnmanaged(File) = .{}, | 179 | files: std.ArrayListUnmanaged(File) = .{}, |
| 196 | hex_digest: [hex_digest_len]u8, | 180 | hex_digest: [hex_digest_len]u8, |
| 197 | debug_bin_digest: DebugBinDigest = null_debug_bin_digest, | | |
| 198 | /// Populated when hit() returns an error because of one | 181 | /// Populated when hit() returns an error because of one |
| 199 | /// of the files listed in the manifest. | 182 | /// of the files listed in the manifest. |
| 200 | failed_file_index: ?usize = null, | 183 | failed_file_index: ?usize = null, |
| ... | @@ -267,31 +250,6 @@ pub const Manifest = struct { | ... | @@ -267,31 +250,6 @@ pub const Manifest = struct { |
| 267 | var bin_digest: BinDigest = undefined; | 250 | var bin_digest: BinDigest = undefined; |
| 268 | self.hash.hasher.final(&bin_digest); | 251 | self.hash.hasher.final(&bin_digest); |
| 269 | | 252 | |
| 270 | if (want_debug_deadlock) { | | |
| 271 | self.debug_bin_digest = bin_digest; | | |
| 272 | | | |
| 273 | const held = all_cache_digest_lock.acquire(); | | |
| 274 | defer held.release(); | | |
| 275 | | | |
| 276 | if (all_cache_digest_allocator) |prev_gpa| { | | |
| 277 | if (prev_gpa != self.cache.gpa) { | | |
| 278 | @panic("The deadlock debug code in Cache depends on using the same allocator for everything"); | | |
| 279 | } | | |
| 280 | } else { | | |
| 281 | all_cache_digest_allocator = self.cache.gpa; | | |
| 282 | } | | |
| 283 | | | |
| 284 | const gop = try all_cache_digest_set.getOrPut(self.cache.gpa, bin_digest); | | |
| 285 | if (gop.found_existing) { | | |
| 286 | std.debug.print("Cache deadlock detected in Cache.hit. Manifest has {d} files:\n", .{self.files.items.len}); | | |
| 287 | for (self.files.items) |file| { | | |
| 288 | const p: []const u8 = file.path orelse "(null)"; | | |
| 289 | std.debug.print(" file: {s}\n", .{p}); | | |
| 290 | } | | |
| 291 | @panic("Cache deadlock detected"); | | |
| 292 | } | | |
| 293 | } | | |
| 294 | | | |
| 295 | _ = std.fmt.bufPrint(&self.hex_digest, "{x}", .{bin_digest}) catch unreachable; | 253 | _ = std.fmt.bufPrint(&self.hex_digest, "{x}", .{bin_digest}) catch unreachable; |
| 296 | | 254 | |
| 297 | self.hash.hasher = hasher_init; | 255 | self.hash.hasher = hasher_init; |
| ... | @@ -628,10 +586,8 @@ pub const Manifest = struct { | ... | @@ -628,10 +586,8 @@ pub const Manifest = struct { |
| 628 | pub fn toOwnedLock(self: *Manifest) Lock { | 586 | pub fn toOwnedLock(self: *Manifest) Lock { |
| 629 | const lock: Lock = .{ | 587 | const lock: Lock = .{ |
| 630 | .manifest_file = self.manifest_file.?, | 588 | .manifest_file = self.manifest_file.?, |
| 631 | .debug_bin_digest = self.debug_bin_digest, | | |
| 632 | }; | 589 | }; |
| 633 | self.manifest_file = null; | 590 | self.manifest_file = null; |
| 634 | self.debug_bin_digest = null_debug_bin_digest; | | |
| 635 | return lock; | 591 | return lock; |
| 636 | } | 592 | } |
| 637 | | 593 | |
| ... | @@ -639,14 +595,6 @@ pub const Manifest = struct { | ... | @@ -639,14 +595,6 @@ pub const Manifest = struct { |
| 639 | /// `Manifest.hit` must be called first. | 595 | /// `Manifest.hit` must be called first. |
| 640 | /// Don't forget to call `writeManifest` before this! | 596 | /// Don't forget to call `writeManifest` before this! |
| 641 | pub fn deinit(self: *Manifest) void { | 597 | pub fn deinit(self: *Manifest) void { |
| 642 | if (want_debug_deadlock) { | | |
| 643 | if (!mem.eql(u8, &self.debug_bin_digest, &null_debug_bin_digest)) { | | |
| 644 | const held = all_cache_digest_lock.acquire(); | | |
| 645 | defer held.release(); | | |
| 646 | | | |
| 647 | all_cache_digest_set.removeAssertDiscard(self.debug_bin_digest); | | |
| 648 | } | | |
| 649 | } | | |
| 650 | if (self.manifest_file) |file| { | 598 | if (self.manifest_file) |file| { |
| 651 | file.close(); | 599 | file.close(); |
| 652 | } | 600 | } |
| ... | @@ -725,22 +673,11 @@ fn isProblematicTimestamp(fs_clock: i128) bool { | ... | @@ -725,22 +673,11 @@ fn isProblematicTimestamp(fs_clock: i128) bool { |
| 725 | return wall_nsec == fs_nsec and wall_sec == fs_sec; | 673 | return wall_nsec == fs_nsec and wall_sec == fs_sec; |
| 726 | } | 674 | } |
| 727 | | 675 | |
| 728 | pub fn deinitDebugMap() void { | | |
| 729 | if (!want_debug_deadlock) return; | | |
| 730 | | | |
| 731 | if (all_cache_digest_set.count() != 0) { | | |
| 732 | @panic("there's a Cache not deinitialized somewhere"); | | |
| 733 | } | | |
| 734 | const gpa = all_cache_digest_allocator orelse return; | | |
| 735 | all_cache_digest_set.clearAndFree(gpa); | | |
| 736 | } | | |
| 737 | | | |
| 738 | test "cache file and then recall it" { | 676 | test "cache file and then recall it" { |
| 739 | if (std.Target.current.os.tag == .wasi) { | 677 | if (std.Target.current.os.tag == .wasi) { |
| 740 | // https://github.com/ziglang/zig/issues/5437 | 678 | // https://github.com/ziglang/zig/issues/5437 |
| 741 | return error.SkipZigTest; | 679 | return error.SkipZigTest; |
| 742 | } | 680 | } |
| 743 | defer deinitDebugMap(); | | |
| 744 | | 681 | |
| 745 | const cwd = fs.cwd(); | 682 | const cwd = fs.cwd(); |
| 746 | | 683 | |
| ... | @@ -819,7 +756,6 @@ test "check that changing a file makes cache fail" { | ... | @@ -819,7 +756,6 @@ test "check that changing a file makes cache fail" { |
| 819 | // https://github.com/ziglang/zig/issues/5437 | 756 | // https://github.com/ziglang/zig/issues/5437 |
| 820 | return error.SkipZigTest; | 757 | return error.SkipZigTest; |
| 821 | } | 758 | } |
| 822 | defer deinitDebugMap(); | | |
| 823 | const cwd = fs.cwd(); | 759 | const cwd = fs.cwd(); |
| 824 | | 760 | |
| 825 | const temp_file = "cache_hash_change_file_test.txt"; | 761 | const temp_file = "cache_hash_change_file_test.txt"; |
| ... | @@ -896,7 +832,6 @@ test "no file inputs" { | ... | @@ -896,7 +832,6 @@ test "no file inputs" { |
| 896 | // https://github.com/ziglang/zig/issues/5437 | 832 | // https://github.com/ziglang/zig/issues/5437 |
| 897 | return error.SkipZigTest; | 833 | return error.SkipZigTest; |
| 898 | } | 834 | } |
| 899 | defer deinitDebugMap(); | | |
| 900 | const cwd = fs.cwd(); | 835 | const cwd = fs.cwd(); |
| 901 | const temp_manifest_dir = "no_file_inputs_manifest_dir"; | 836 | const temp_manifest_dir = "no_file_inputs_manifest_dir"; |
| 902 | defer cwd.deleteTree(temp_manifest_dir) catch {}; | 837 | defer cwd.deleteTree(temp_manifest_dir) catch {}; |
| ... | @@ -942,7 +877,6 @@ test "Manifest with files added after initial hash work" { | ... | @@ -942,7 +877,6 @@ test "Manifest with files added after initial hash work" { |
| 942 | // https://github.com/ziglang/zig/issues/5437 | 877 | // https://github.com/ziglang/zig/issues/5437 |
| 943 | return error.SkipZigTest; | 878 | return error.SkipZigTest; |
| 944 | } | 879 | } |
| 945 | defer deinitDebugMap(); | | |
| 946 | const cwd = fs.cwd(); | 880 | const cwd = fs.cwd(); |
| 947 | | 881 | |
| 948 | const temp_file1 = "cache_hash_post_file_test1.txt"; | 882 | const temp_file1 = "cache_hash_post_file_test1.txt"; |