authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-24 16:58:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-24 16:58:01-07:00
logfdcac5ecbd324170f7281f6704ead18b7d904e72
tree9056babb5c72e9bf530ae6719334d2c4cd8e7bc2
parent02b8d881539a665212b4ce4c174329cfd503ab54

stage2: add cleanup logic for EmbedFile

It was never implemented, leading to a memory leak that was caught when test coverage for the compile error was added.

1 files changed, 19 insertions(+), 1 deletions(-)

src/Module.zig+19-1
...@@ -1571,6 +1571,13 @@ pub const EmbedFile = struct {...@@ -1571,6 +1571,13 @@ pub const EmbedFile = struct {
1571 /// This is how zig knows what other Decl objects to invalidate if the file1571 /// This is how zig knows what other Decl objects to invalidate if the file
1572 /// changes on disk.1572 /// changes on disk.
1573 owner_decl: *Decl,1573 owner_decl: *Decl,
1574
1575 fn destroy(embed_file: *EmbedFile, mod: *Module) void {
1576 const gpa = mod.gpa;
1577 gpa.free(embed_file.sub_file_path);
1578 gpa.free(embed_file.bytes);
1579 gpa.destroy(embed_file);
1580 }
1574};1581};
15751582
1576/// This struct holds data necessary to construct API-facing `AllErrors.Message`.1583/// This struct holds data necessary to construct API-facing `AllErrors.Message`.
...@@ -2359,6 +2366,15 @@ pub fn deinit(mod: *Module) void {...@@ -2359,6 +2366,15 @@ pub fn deinit(mod: *Module) void {
2359 }2366 }
2360 mod.import_table.deinit(gpa);2367 mod.import_table.deinit(gpa);
23612368
2369 {
2370 var it = mod.embed_table.iterator();
2371 while (it.next()) |entry| {
2372 gpa.free(entry.key_ptr.*);
2373 entry.value_ptr.*.destroy(mod);
2374 }
2375 mod.embed_table.deinit(gpa);
2376 }
2377
2362 mod.deletion_set.deinit(gpa);2378 mod.deletion_set.deinit(gpa);
23632379
2364 // The callsite of `Compilation.create` owns the `main_pkg`, however2380 // The callsite of `Compilation.create` owns the `main_pkg`, however
...@@ -3642,7 +3658,7 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb...@@ -3642,7 +3658,7 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb
36423658
3643 const gop = try mod.embed_table.getOrPut(gpa, resolved_path);3659 const gop = try mod.embed_table.getOrPut(gpa, resolved_path);
3644 if (gop.found_existing) return gop.value_ptr.*;3660 if (gop.found_existing) return gop.value_ptr.*;
3645 keep_resolved_path = true; // It's now owned by embed_table.3661 errdefer assert(mod.embed_table.remove(resolved_path));
36463662
3647 const new_file = try gpa.create(EmbedFile);3663 const new_file = try gpa.create(EmbedFile);
3648 errdefer gpa.destroy(new_file);3664 errdefer gpa.destroy(new_file);
...@@ -3663,11 +3679,13 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb...@@ -3663,11 +3679,13 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb
3663 const stat = try file.stat();3679 const stat = try file.stat();
3664 const size_usize = try std.math.cast(usize, stat.size);3680 const size_usize = try std.math.cast(usize, stat.size);
3665 const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);3681 const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);
3682 errdefer gpa.free(bytes);
36663683
3667 log.debug("new embedFile. resolved_root_path={s}, resolved_path={s}, sub_file_path={s}, rel_file_path={s}", .{3684 log.debug("new embedFile. resolved_root_path={s}, resolved_path={s}, sub_file_path={s}, rel_file_path={s}", .{
3668 resolved_root_path, resolved_path, sub_file_path, rel_file_path,3685 resolved_root_path, resolved_path, sub_file_path, rel_file_path,
3669 });3686 });
36703687
3688 keep_resolved_path = true; // It's now owned by embed_table.
3671 gop.value_ptr.* = new_file;3689 gop.value_ptr.* = new_file;
3672 new_file.* = .{3690 new_file.* = .{
3673 .sub_file_path = sub_file_path,3691 .sub_file_path = sub_file_path,