mirror of
https://github.com/ziglang/zig.git
synced 2025-12-15 02:33:07 +00:00
stage2: fix memory leak of emit_bin.sub_path
Instead of juggling GPA-allocated sub_path (and ultimately dropping the ball, in this analogy), `Compilation.create` allocates an already-exactly-correct size `sub_path` that has the digest unpopulated. This is then overwritten in place as necessary and used as the `emit_bin.sub_path` value, and no allocations/frees are performed for this file path.
This commit is contained in:
parent
208a6c7d6a
commit
73ba6bf30b
@ -98,9 +98,11 @@ clang_argv: []const []const u8,
|
|||||||
cache_parent: *Cache,
|
cache_parent: *Cache,
|
||||||
/// Path to own executable for invoking `zig clang`.
|
/// Path to own executable for invoking `zig clang`.
|
||||||
self_exe_path: ?[]const u8,
|
self_exe_path: ?[]const u8,
|
||||||
/// null means -fno-emit-bin. Contains the basename of the
|
/// null means -fno-emit-bin.
|
||||||
/// outputted binary file in case we don't know the directory yet.
|
/// This is mutable memory allocated into the Compilation-lifetime arena (`arena_state`)
|
||||||
whole_bin_basename: ?[]const u8,
|
/// of exactly the correct size for "o/[digest]/[basename]".
|
||||||
|
/// The basename is of the outputted binary file in case we don't know the directory yet.
|
||||||
|
whole_bin_sub_path: ?[]u8,
|
||||||
zig_lib_directory: Directory,
|
zig_lib_directory: Directory,
|
||||||
local_cache_directory: Directory,
|
local_cache_directory: Directory,
|
||||||
global_cache_directory: Directory,
|
global_cache_directory: Directory,
|
||||||
@ -1487,9 +1489,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
|||||||
// can use it for communicating the result directory via `bin_file.emit`.
|
// can use it for communicating the result directory via `bin_file.emit`.
|
||||||
// This is used to distinguish between -fno-emit-bin and -femit-bin
|
// This is used to distinguish between -fno-emit-bin and -femit-bin
|
||||||
// for `CacheMode.whole`.
|
// for `CacheMode.whole`.
|
||||||
const whole_bin_basename: ?[]const u8 = if (options.emit_bin) |x|
|
// This memory will be overwritten with the real digest in update() but
|
||||||
|
// the basename will be preserved.
|
||||||
|
const whole_bin_sub_path: ?[]u8 = if (options.emit_bin) |x|
|
||||||
if (x.directory == null)
|
if (x.directory == null)
|
||||||
x.basename
|
try std.fmt.allocPrint(arena, "o" ++ std.fs.path.sep_str ++
|
||||||
|
("x" ** Cache.hex_digest_len) ++ std.fs.path.sep_str ++ "{s}", .{x.basename})
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
@ -1600,7 +1605,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
|||||||
.local_cache_directory = options.local_cache_directory,
|
.local_cache_directory = options.local_cache_directory,
|
||||||
.global_cache_directory = options.global_cache_directory,
|
.global_cache_directory = options.global_cache_directory,
|
||||||
.bin_file = bin_file,
|
.bin_file = bin_file,
|
||||||
.whole_bin_basename = whole_bin_basename,
|
.whole_bin_sub_path = whole_bin_sub_path,
|
||||||
.emit_asm = options.emit_asm,
|
.emit_asm = options.emit_asm,
|
||||||
.emit_llvm_ir = options.emit_llvm_ir,
|
.emit_llvm_ir = options.emit_llvm_ir,
|
||||||
.emit_llvm_bc = options.emit_llvm_bc,
|
.emit_llvm_bc = options.emit_llvm_bc,
|
||||||
@ -1665,7 +1670,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
|||||||
comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});
|
comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
const have_bin_emit = comp.bin_file.options.emit != null or comp.whole_bin_basename != null;
|
const have_bin_emit = comp.bin_file.options.emit != null or comp.whole_bin_sub_path != null;
|
||||||
|
|
||||||
if (have_bin_emit and !comp.bin_file.options.skip_linker_dependencies) {
|
if (have_bin_emit and !comp.bin_file.options.skip_linker_dependencies) {
|
||||||
// If we need to build glibc for the target, add work items for it.
|
// If we need to build glibc for the target, add work items for it.
|
||||||
@ -1941,19 +1946,7 @@ pub fn update(comp: *Compilation) !void {
|
|||||||
log.debug("CacheMode.whole cache hit for {s}", .{comp.bin_file.options.root_name});
|
log.debug("CacheMode.whole cache hit for {s}", .{comp.bin_file.options.root_name});
|
||||||
const digest = man.final();
|
const digest = man.final();
|
||||||
|
|
||||||
// Communicate the output binary location to parent Compilations.
|
comp.wholeCacheModeSetBinFilePath(&digest);
|
||||||
if (comp.whole_bin_basename) |basename| {
|
|
||||||
const new_sub_path = try std.fs.path.join(comp.gpa, &.{
|
|
||||||
"o", &digest, basename,
|
|
||||||
});
|
|
||||||
if (comp.bin_file.options.emit) |emit| {
|
|
||||||
comp.gpa.free(emit.sub_path);
|
|
||||||
}
|
|
||||||
comp.bin_file.options.emit = .{
|
|
||||||
.directory = comp.local_cache_directory,
|
|
||||||
.sub_path = new_sub_path,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(comp.bin_file.lock == null);
|
assert(comp.bin_file.lock == null);
|
||||||
comp.bin_file.lock = man.toOwnedLock();
|
comp.bin_file.lock = man.toOwnedLock();
|
||||||
@ -1989,13 +1982,10 @@ pub fn update(comp: *Compilation) !void {
|
|||||||
// This resets the link.File to operate as if we called openPath() in create()
|
// This resets the link.File to operate as if we called openPath() in create()
|
||||||
// instead of simulating -fno-emit-bin.
|
// instead of simulating -fno-emit-bin.
|
||||||
var options = comp.bin_file.options;
|
var options = comp.bin_file.options;
|
||||||
if (comp.whole_bin_basename) |basename| {
|
if (comp.whole_bin_sub_path) |sub_path| {
|
||||||
if (options.emit) |emit| {
|
|
||||||
comp.gpa.free(emit.sub_path);
|
|
||||||
}
|
|
||||||
options.emit = .{
|
options.emit = .{
|
||||||
.directory = tmp_artifact_directory.?,
|
.directory = tmp_artifact_directory.?,
|
||||||
.sub_path = basename,
|
.sub_path = std.fs.path.basename(sub_path),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
comp.bin_file.destroy();
|
comp.bin_file.destroy();
|
||||||
@ -2149,13 +2139,7 @@ pub fn update(comp: *Compilation) !void {
|
|||||||
log.warn("failed to write cache manifest: {s}", .{@errorName(err)});
|
log.warn("failed to write cache manifest: {s}", .{@errorName(err)});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Communicate the output binary location to parent Compilations.
|
comp.wholeCacheModeSetBinFilePath(&digest);
|
||||||
if (comp.whole_bin_basename) |basename| {
|
|
||||||
comp.bin_file.options.emit = .{
|
|
||||||
.directory = comp.local_cache_directory,
|
|
||||||
.sub_path = try std.fs.path.join(comp.gpa, &.{ "o", &digest, basename }),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(comp.bin_file.lock == null);
|
assert(comp.bin_file.lock == null);
|
||||||
comp.bin_file.lock = man.toOwnedLock();
|
comp.bin_file.lock = man.toOwnedLock();
|
||||||
@ -2163,6 +2147,18 @@ pub fn update(comp: *Compilation) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Communicate the output binary location to parent Compilations.
|
||||||
|
fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_digest_len]u8) void {
|
||||||
|
const sub_path = comp.whole_bin_sub_path orelse return;
|
||||||
|
const digest_start = 2; // "o/[digest]/[basename]"
|
||||||
|
mem.copy(u8, sub_path[digest_start..], digest);
|
||||||
|
|
||||||
|
comp.bin_file.options.emit = .{
|
||||||
|
.directory = comp.local_cache_directory,
|
||||||
|
.sub_path = sub_path,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// This is only observed at compile-time and used to emit a compile error
|
/// This is only observed at compile-time and used to emit a compile error
|
||||||
/// to remind the programmer to update multiple related pieces of code that
|
/// to remind the programmer to update multiple related pieces of code that
|
||||||
/// are in different locations. Bump this number when adding or deleting
|
/// are in different locations. Bump this number when adding or deleting
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user