diff --git a/src/Cache.zig b/src/Cache.zig index e22335daa..da9e62e24 100644 --- a/src/Cache.zig +++ b/src/Cache.zig @@ -16,8 +16,8 @@ const Allocator = std.mem.Allocator; /// This protection is conditionally compiled depending on `want_debug_deadlock`. var all_cache_digest_set: std.AutoHashMapUnmanaged(BinDigest, void) = .{}; var all_cache_digest_lock: std.Mutex = .{}; -// TODO: Figure out how to make sure that `all_cache_digest_set` does not leak memory! -pub const want_debug_deadlock = false; +var all_cache_digest_allocator: ?*Allocator = null; +const want_debug_deadlock = std.debug.runtime_safety; const DebugBinDigest = if (want_debug_deadlock) BinDigest else void; const null_debug_bin_digest = if (want_debug_deadlock) ([1]u8{0} ** bin_digest_len) else {}; @@ -273,6 +273,14 @@ pub const Manifest = struct { const held = all_cache_digest_lock.acquire(); defer held.release(); + if (all_cache_digest_allocator) |prev_gpa| { + if (prev_gpa != self.cache.gpa) { + @panic("The deadlock debug code in Cache depends on using the same allocator for everything"); + } + } else { + all_cache_digest_allocator = self.cache.gpa; + } + const gop = try all_cache_digest_set.getOrPut(self.cache.gpa, bin_digest); if (gop.found_existing) { std.debug.print("Cache deadlock detected in Cache.hit. Manifest has {d} files:\n", .{self.files.items.len}); @@ -717,15 +725,22 @@ fn isProblematicTimestamp(fs_clock: i128) bool { return wall_nsec == fs_nsec and wall_sec == fs_sec; } +pub fn deinitDebugMap() void { + if (!want_debug_deadlock) return; + + if (all_cache_digest_set.count() != 0) { + @panic("there's a Cache not deinitialized somewhere"); + } + const gpa = all_cache_digest_allocator orelse return; + all_cache_digest_set.clearAndFree(gpa); +} + test "cache file and then recall it" { if (std.Target.current.os.tag == .wasi) { // https://github.com/ziglang/zig/issues/5437 return error.SkipZigTest; } - defer if (want_debug_deadlock) { - testing.expect(all_cache_digest_set.count() == 0); - all_cache_digest_set.clearAndFree(testing.allocator); - }; + defer deinitDebugMap(); const cwd = fs.cwd(); @@ -804,10 +819,7 @@ test "check that changing a file makes cache fail" { // https://github.com/ziglang/zig/issues/5437 return error.SkipZigTest; } - defer if (want_debug_deadlock) { - testing.expect(all_cache_digest_set.count() == 0); - all_cache_digest_set.clearAndFree(testing.allocator); - }; + defer deinitDebugMap(); const cwd = fs.cwd(); const temp_file = "cache_hash_change_file_test.txt"; @@ -884,10 +896,7 @@ test "no file inputs" { // https://github.com/ziglang/zig/issues/5437 return error.SkipZigTest; } - defer if (want_debug_deadlock) { - testing.expect(all_cache_digest_set.count() == 0); - all_cache_digest_set.clearAndFree(testing.allocator); - }; + defer deinitDebugMap(); const cwd = fs.cwd(); const temp_manifest_dir = "no_file_inputs_manifest_dir"; defer cwd.deleteTree(temp_manifest_dir) catch {}; @@ -933,10 +942,7 @@ test "Manifest with files added after initial hash work" { // https://github.com/ziglang/zig/issues/5437 return error.SkipZigTest; } - defer if (want_debug_deadlock) { - testing.expect(all_cache_digest_set.count() == 0); - all_cache_digest_set.clearAndFree(testing.allocator); - }; + defer deinitDebugMap(); const cwd = fs.cwd(); const temp_file1 = "cache_hash_post_file_test1.txt"; diff --git a/src/main.zig b/src/main.zig index 155dcc74d..cf941104a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -104,7 +104,10 @@ pub fn log( var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; pub fn main() anyerror!void { - const gpa = if (std.builtin.link_libc) std.heap.raw_c_allocator else &general_purpose_allocator.allocator; + const gpa = if (std.builtin.link_libc) + std.heap.raw_c_allocator + else + &general_purpose_allocator.allocator; defer if (!std.builtin.link_libc) { _ = general_purpose_allocator.deinit(); }; @@ -3289,6 +3292,7 @@ fn detectNativeTargetInfo(gpa: *Allocator, cross_target: std.zig.CrossTarget) !s /// calls exit(0), and does not return. pub fn cleanExit() void { if (std.builtin.mode == .Debug) { + Cache.deinitDebugMap(); return; } else { process.exit(0); diff --git a/src/test.zig b/src/test.zig index 67a30f1f3..6dd55643d 100644 --- a/src/test.zig +++ b/src/test.zig @@ -518,6 +518,7 @@ pub const TestContext = struct { case.updates.deinit(); } self.cases.deinit(); + @import("Cache.zig").deinitDebugMap(); self.* = undefined; }