| author | |
| committer | |
| log | c102eb83e6ab4c3a6cbcecf87964150c0b3df463 |
| tree | 15eef1193ace606d4a4b2178ccbf2d4c19c9eb78 |
| parent | 8591f30b0d53a597682bebdfcd570f5f44339b26 |
| signature |
Without this commit we leak file descriptors and memory2 files changed, 60 insertions(+), 58 deletions(-)
src/Package.zig+34-22| ... | ... | @@ -1,3 +1,12 @@ |
| 1 | const Package = @This(); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | const fs = std.fs; | |
| 5 | const mem = std.mem; | |
| 6 | const Allocator = mem.Allocator; | |
| 7 | ||
| 8 | const Compilation = @import("Compilation.zig"); | |
| 9 | ||
| 1 | 10 | pub const Table = std.StringHashMapUnmanaged(*Package); |
| 2 | 11 | |
| 3 | 12 | root_src_directory: Compilation.Directory, |
| ... | ... | @@ -6,57 +15,60 @@ root_src_path: []const u8, |
| 6 | 15 | table: Table = .{}, |
| 7 | 16 | parent: ?*Package = null, |
| 8 | 17 | |
| 9 | const std = @import("std"); | |
| 10 | const mem = std.mem; | |
| 11 | const Allocator = std.mem.Allocator; | |
| 12 | const assert = std.debug.assert; | |
| 13 | const Package = @This(); | |
| 14 | const Compilation = @import("Compilation.zig"); | |
| 15 | ||
| 16 | /// No references to `root_src_dir` and `root_src_path` are kept. | |
| 18 | /// Allocate a Package. No references to the slices passed are kept. | |
| 17 | 19 | pub fn create( |
| 18 | 20 | gpa: *Allocator, |
| 19 | base_directory: Compilation.Directory, | |
| 20 | /// Relative to `base_directory`. | |
| 21 | root_src_dir: []const u8, | |
| 22 | /// Relative to `root_src_dir`. | |
| 21 | /// Null indicates the current working directory | |
| 22 | root_src_dir_path: ?[]const u8, | |
| 23 | /// Relative to root_src_dir_path | |
| 23 | 24 | root_src_path: []const u8, |
| 24 | 25 | ) !*Package { |
| 25 | 26 | const ptr = try gpa.create(Package); |
| 26 | 27 | errdefer gpa.destroy(ptr); |
| 27 | 28 | |
| 28 | const root_src_dir_path = try base_directory.join(gpa, &[_][]const u8{root_src_dir}); | |
| 29 | errdefer gpa.free(root_src_dir_path); | |
| 29 | const owned_dir_path = if (root_src_dir_path) |p| try gpa.dupe(u8, p) else null; | |
| 30 | errdefer if (owned_dir_path) |p| gpa.free(p); | |
| 30 | 31 | |
| 31 | const root_src_path_dupe = try mem.dupe(gpa, u8, root_src_path); | |
| 32 | errdefer gpa.free(root_src_path_dupe); | |
| 32 | const owned_src_path = try gpa.dupe(u8, root_src_path); | |
| 33 | errdefer gpa.free(owned_src_path); | |
| 33 | 34 | |
| 34 | 35 | ptr.* = .{ |
| 35 | 36 | .root_src_directory = .{ |
| 36 | .path = root_src_dir_path, | |
| 37 | .handle = try base_directory.handle.openDir(root_src_dir, .{}), | |
| 37 | .path = owned_dir_path, | |
| 38 | .handle = if (owned_dir_path) |p| try fs.cwd().openDir(p, .{}) else fs.cwd(), | |
| 38 | 39 | }, |
| 39 | .root_src_path = root_src_path_dupe, | |
| 40 | .root_src_path = owned_src_path, | |
| 40 | 41 | }; |
| 42 | ||
| 41 | 43 | return ptr; |
| 42 | 44 | } |
| 43 | 45 | |
| 46 | /// Free all memory associated with this package and recursively call destroy | |
| 47 | /// on all packages in its table | |
| 44 | 48 | pub fn destroy(pkg: *Package, gpa: *Allocator) void { |
| 45 | pkg.root_src_directory.handle.close(); | |
| 46 | 49 | gpa.free(pkg.root_src_path); |
| 47 | if (pkg.root_src_directory.path) |p| gpa.free(p); | |
| 50 | ||
| 51 | // If root_src_directory.path is null then the handle is the cwd() | |
| 52 | // which shouldn't be closed. | |
| 53 | if (pkg.root_src_directory.path) |p| { | |
| 54 | gpa.free(p); | |
| 55 | pkg.root_src_directory.handle.close(); | |
| 56 | } | |
| 57 | ||
| 48 | 58 | { |
| 49 | 59 | var it = pkg.table.iterator(); |
| 50 | 60 | while (it.next()) |kv| { |
| 61 | kv.value.destroy(gpa); | |
| 51 | 62 | gpa.free(kv.key); |
| 52 | 63 | } |
| 53 | 64 | } |
| 65 | ||
| 54 | 66 | pkg.table.deinit(gpa); |
| 55 | 67 | gpa.destroy(pkg); |
| 56 | 68 | } |
| 57 | 69 | |
| 58 | 70 | pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package) !void { |
| 59 | try pkg.table.ensureCapacity(gpa, pkg.table.items().len + 1); | |
| 71 | try pkg.table.ensureCapacity(gpa, pkg.table.count() + 1); | |
| 60 | 72 | const name_dupe = try mem.dupe(gpa, u8, name); |
| 61 | 73 | pkg.table.putAssumeCapacityNoClobber(name_dupe, package); |
| 62 | 74 | } |
src/main.zig+26-36| ... | ... | @@ -560,12 +560,15 @@ fn buildOutputType( |
| 560 | 560 | var test_exec_args = std.ArrayList(?[]const u8).init(gpa); |
| 561 | 561 | defer test_exec_args.deinit(); |
| 562 | 562 | |
| 563 | var root_pkg_memory: Package = .{ | |
| 564 | .root_src_directory = undefined, | |
| 565 | .root_src_path = undefined, | |
| 563 | const pkg_tree_root = try gpa.create(Package); | |
| 564 | // This package only exists to clean up the code parsing --pkg-begin and | |
| 565 | // --pkg-end flags. Use dummy values that are safe for the destroy call. | |
| 566 | pkg_tree_root.* = .{ | |
| 567 | .root_src_directory = .{ .path = null, .handle = fs.cwd() }, | |
| 568 | .root_src_path = &[0]u8{}, | |
| 566 | 569 | }; |
| 567 | defer root_pkg_memory.table.deinit(gpa); | |
| 568 | var cur_pkg: *Package = &root_pkg_memory; | |
| 570 | defer pkg_tree_root.destroy(gpa); | |
| 571 | var cur_pkg: *Package = pkg_tree_root; | |
| 569 | 572 | |
| 570 | 573 | switch (arg_mode) { |
| 571 | 574 | .build, .translate_c, .zig_test, .run => { |
| ... | ... | @@ -619,22 +622,13 @@ fn buildOutputType( |
| 619 | 622 | i += 1; |
| 620 | 623 | const pkg_path = args[i]; |
| 621 | 624 | |
| 622 | const new_cur_pkg = try arena.create(Package); | |
| 623 | new_cur_pkg.* = .{ | |
| 624 | .root_src_directory = if (fs.path.dirname(pkg_path)) |dirname| | |
| 625 | .{ | |
| 626 | .path = dirname, | |
| 627 | .handle = try fs.cwd().openDir(dirname, .{}), // TODO close this fd | |
| 628 | } | |
| 629 | else | |
| 630 | .{ | |
| 631 | .path = null, | |
| 632 | .handle = fs.cwd(), | |
| 633 | }, | |
| 634 | .root_src_path = fs.path.basename(pkg_path), | |
| 635 | .parent = cur_pkg, | |
| 636 | }; | |
| 637 | try cur_pkg.table.put(gpa, pkg_name, new_cur_pkg); | |
| 625 | const new_cur_pkg = try Package.create( | |
| 626 | gpa, | |
| 627 | fs.path.dirname(pkg_path), | |
| 628 | fs.path.basename(pkg_path), | |
| 629 | ); | |
| 630 | new_cur_pkg.parent = cur_pkg; | |
| 631 | try cur_pkg.add(gpa, pkg_name, new_cur_pkg); | |
| 638 | 632 | cur_pkg = new_cur_pkg; |
| 639 | 633 | } else if (mem.eql(u8, arg, "--pkg-end")) { |
| 640 | 634 | cur_pkg = cur_pkg.parent orelse |
| ... | ... | @@ -1583,26 +1577,22 @@ fn buildOutputType( |
| 1583 | 1577 | .yes => |p| p, |
| 1584 | 1578 | }; |
| 1585 | 1579 | |
| 1586 | var cleanup_root_dir: ?fs.Dir = null; | |
| 1587 | defer if (cleanup_root_dir) |*dir| dir.close(); | |
| 1588 | ||
| 1589 | 1580 | const root_pkg: ?*Package = if (root_src_file) |src_path| blk: { |
| 1590 | 1581 | if (main_pkg_path) |p| { |
| 1591 | const dir = try fs.cwd().openDir(p, .{}); | |
| 1592 | cleanup_root_dir = dir; | |
| 1593 | root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir }; | |
| 1594 | root_pkg_memory.root_src_path = try fs.path.relative(arena, p, src_path); | |
| 1595 | } else if (fs.path.dirname(src_path)) |p| { | |
| 1596 | const dir = try fs.cwd().openDir(p, .{}); | |
| 1597 | cleanup_root_dir = dir; | |
| 1598 | root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir }; | |
| 1599 | root_pkg_memory.root_src_path = fs.path.basename(src_path); | |
| 1582 | const rel_src_path = try fs.path.relative(gpa, p, src_path); | |
| 1583 | defer gpa.free(rel_src_path); | |
| 1584 | break :blk try Package.create(gpa, p, rel_src_path); | |
| 1600 | 1585 | } else { |
| 1601 | root_pkg_memory.root_src_directory = .{ .path = null, .handle = fs.cwd() }; | |
| 1602 | root_pkg_memory.root_src_path = src_path; | |
| 1586 | break :blk try Package.create(gpa, fs.path.dirname(src_path), fs.path.basename(src_path)); | |
| 1603 | 1587 | } |
| 1604 | break :blk &root_pkg_memory; | |
| 1605 | 1588 | } else null; |
| 1589 | defer if (root_pkg) |p| p.destroy(gpa); | |
| 1590 | ||
| 1591 | // Transfer packages added with --pkg-begin/--pkg-end to the root package | |
| 1592 | if (root_pkg) |pkg| { | |
| 1593 | pkg.table = pkg_tree_root.table; | |
| 1594 | pkg_tree_root.table = .{}; | |
| 1595 | } | |
| 1606 | 1596 | |
| 1607 | 1597 | const self_exe_path = try fs.selfExePathAlloc(arena); |
| 1608 | 1598 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| |