diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-16 17:11:44 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-16 17:30:25 +0100 |
| commit | 76afdd0586dc646bee1f20fd9ff23c044d70a211 (patch) | |
| tree | 1c7e56b81b76ed53fc27b72e7d0242866417ceb7 /src/link | |
| parent | e1e414e62a86cc460ef215ea8050c953b68b6080 (diff) | |
| download | zig-76afdd0586dc646bee1f20fd9ff23c044d70a211.tar.gz zig-76afdd0586dc646bee1f20fd9ff23c044d70a211.zip | |
link: move macOS kernel inode cache invalidation to MachO linker
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/MachO.zig | 17 | ||||
| -rw-r--r-- | src/link/MachO/zld.zig | 1 |
2 files changed, 18 insertions, 0 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index eaf16e4009..368914e1be 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -662,6 +662,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No if (codesig) |*csig| { try self.writeCodeSignature(comp, csig); // code signing always comes last + const emit = self.base.options.emit.?; + try invalidateKernelCache(emit.directory.handle, emit.sub_path); } if (self.d_sym) |*d_sym| { @@ -691,6 +693,21 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No self.cold_start = false; } + +/// XNU starting with Big Sur running on arm64 is caching inodes of running binaries. +/// Any change to the binary will effectively invalidate the kernel's cache +/// resulting in a SIGKILL on each subsequent run. Since when doing incremental +/// linking we're modifying a binary in-place, this will end up with the kernel +/// killing it on every subsequent run. To circumvent it, we will copy the file +/// into a new inode, remove the original file, and rename the copy to match +/// the original file. This is super messy, but there doesn't seem any other +/// way to please the XNU. +pub fn invalidateKernelCache(dir: std.fs.Dir, sub_path: []const u8) !void { + if (comptime builtin.target.isDarwin() and builtin.target.cpu.arch == .aarch64) { + try dir.copyFile(sub_path, dir, sub_path, .{}); + } +} + inline fn conformUuid(out: *[Md5.digest_length]u8) void { // LC_UUID uuids should conform to RFC 4122 UUID version 4 & UUID version 5 formats out[6] = (out[6] & 0x0F) | (3 << 4); diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index a901e4fd4b..a7c7bc41b9 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -4172,6 +4172,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr if (codesig) |*csig| { try zld.writeCodeSignature(comp, csig); // code signing always comes last + try MachO.invalidateKernelCache(directory.handle, zld.options.emit.?.sub_path); } } |
