authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-02 22:37:07-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-15 10:48:13-07:00
log9bf63b09963ca6ea1179dfaa9142498556bfac9d
tree61bc3e7308c21eb2dab6432a358be97e896edb1b
parent7ffdbb3b855ef9e4aa25a8ac911fce752a71e16d

stage2: avoid linux-only APIs on other operating systems


5 files changed, 57 insertions(+), 38 deletions(-)

src/Compilation.zig+1-1
...@@ -1847,7 +1847,7 @@ fn cleanupTmpArtifactDirectory(...@@ -1847,7 +1847,7 @@ fn cleanupTmpArtifactDirectory(
1847 }1847 }
1848}1848}
18491849
1850pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.os.pid_t) !void {1850pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.ChildProcess.Id) !void {
1851 comp.bin_file.child_pid = pid;1851 comp.bin_file.child_pid = pid;
1852 try comp.makeBinFileWritable();1852 try comp.makeBinFileWritable();
1853 try comp.update(prog_node);1853 try comp.update(prog_node);
src/link.zig+18-8
...@@ -264,7 +264,7 @@ pub const File = struct {...@@ -264,7 +264,7 @@ pub const File = struct {
264 /// of this linking operation.264 /// of this linking operation.
265 lock: ?Cache.Lock = null,265 lock: ?Cache.Lock = null,
266266
267 child_pid: ?std.os.pid_t = null,267 child_pid: ?std.ChildProcess.Id = null,
268268
269 /// Attempts incremental linking, if the file already exists. If269 /// Attempts incremental linking, if the file already exists. If
270 /// incremental linking fails, falls back to truncating the file and270 /// incremental linking fails, falls back to truncating the file and
...@@ -388,10 +388,14 @@ pub const File = struct {...@@ -388,10 +388,14 @@ pub const File = struct {
388 });388 });
389 try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, tmp_sub_path, .{});389 try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, tmp_sub_path, .{});
390 try emit.directory.handle.rename(tmp_sub_path, emit.sub_path);390 try emit.directory.handle.rename(tmp_sub_path, emit.sub_path);
391391 switch (builtin.os.tag) {
392 switch (std.os.errno(std.os.linux.ptrace(std.os.linux.PTRACE.ATTACH, pid, 0, 0, 0))) {392 .linux => {
393 .SUCCESS => {},393 switch (std.os.errno(std.os.linux.ptrace(std.os.linux.PTRACE.ATTACH, pid, 0, 0, 0))) {
394 else => |errno| log.warn("ptrace failure: {s}", .{@tagName(errno)}),394 .SUCCESS => {},
395 else => |errno| log.warn("ptrace failure: {s}", .{@tagName(errno)}),
396 }
397 },
398 else => return error.HotSwapUnavailableOnHostOperatingSystem,
395 }399 }
396 }400 }
397 base.file = try emit.directory.handle.createFile(emit.sub_path, .{401 base.file = try emit.directory.handle.createFile(emit.sub_path, .{
...@@ -444,9 +448,14 @@ pub const File = struct {...@@ -444,9 +448,14 @@ pub const File = struct {
444 base.file = null;448 base.file = null;
445449
446 if (base.child_pid) |pid| {450 if (base.child_pid) |pid| {
447 switch (std.os.errno(std.os.linux.ptrace(std.os.linux.PTRACE.DETACH, pid, 0, 0, 0))) {451 switch (builtin.os.tag) {
448 .SUCCESS => {},452 .linux => {
449 else => |errno| log.warn("ptrace failure: {s}", .{@tagName(errno)}),453 switch (std.os.errno(std.os.linux.ptrace(std.os.linux.PTRACE.DETACH, pid, 0, 0, 0))) {
454 .SUCCESS => {},
455 else => |errno| log.warn("ptrace failure: {s}", .{@tagName(errno)}),
456 }
457 },
458 else => return error.HotSwapUnavailableOnHostOperatingSystem,
450 }459 }
451 }460 }
452 },461 },
...@@ -487,6 +496,7 @@ pub const File = struct {...@@ -487,6 +496,7 @@ pub const File = struct {
487 NetNameDeleted,496 NetNameDeleted,
488 DeviceBusy,497 DeviceBusy,
489 InvalidArgument,498 InvalidArgument,
499 HotSwapUnavailableOnHostOperatingSystem,
490 };500 };
491501
492 /// Called from within the CodeGen to lower a local variable instantion as an unnamed502 /// Called from within the CodeGen to lower a local variable instantion as an unnamed
src/link/Elf.zig+34-24
...@@ -2453,18 +2453,23 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s...@@ -2453,18 +2453,23 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
2453 const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset;2453 const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset;
24542454
2455 if (self.base.child_pid) |pid| {2455 if (self.base.child_pid) |pid| {
2456 var code_vec: [1]std.os.iovec_const = .{.{2456 switch (builtin.os.tag) {
2457 .iov_base = code.ptr,2457 .linux => {
2458 .iov_len = code.len,2458 var code_vec: [1]std.os.iovec_const = .{.{
2459 }};2459 .iov_base = code.ptr,
2460 var remote_vec: [1]std.os.iovec_const = .{.{2460 .iov_len = code.len,
2461 .iov_base = @intToPtr([*]u8, local_sym.st_value),2461 }};
2462 .iov_len = code.len,2462 var remote_vec: [1]std.os.iovec_const = .{.{
2463 }};2463 .iov_base = @intToPtr([*]u8, local_sym.st_value),
2464 const rc = std.os.linux.process_vm_writev(pid, &code_vec, &remote_vec, 0);2464 .iov_len = code.len,
2465 switch (std.os.errno(rc)) {2465 }};
2466 .SUCCESS => assert(rc == code.len),2466 const rc = std.os.linux.process_vm_writev(pid, &code_vec, &remote_vec, 0);
2467 else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),2467 switch (std.os.errno(rc)) {
2468 .SUCCESS => assert(rc == code.len),
2469 else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
2470 }
2471 },
2472 else => return error.HotSwapUnavailableOnHostOperatingSystem,
2468 }2473 }
2469 }2474 }
24702475
...@@ -2856,18 +2861,23 @@ fn writeOffsetTableEntry(self: *Elf, index: usize) !void {...@@ -2856,18 +2861,23 @@ fn writeOffsetTableEntry(self: *Elf, index: usize) !void {
2856 try self.base.file.?.pwriteAll(&buf, off);2861 try self.base.file.?.pwriteAll(&buf, off);
28572862
2858 if (self.base.child_pid) |pid| {2863 if (self.base.child_pid) |pid| {
2859 var local_vec: [1]std.os.iovec_const = .{.{2864 switch (builtin.os.tag) {
2860 .iov_base = &buf,2865 .linux => {
2861 .iov_len = buf.len,2866 var local_vec: [1]std.os.iovec_const = .{.{
2862 }};2867 .iov_base = &buf,
2863 var remote_vec: [1]std.os.iovec_const = .{.{2868 .iov_len = buf.len,
2864 .iov_base = @intToPtr([*]u8, vaddr),2869 }};
2865 .iov_len = buf.len,2870 var remote_vec: [1]std.os.iovec_const = .{.{
2866 }};2871 .iov_base = @intToPtr([*]u8, vaddr),
2867 const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0);2872 .iov_len = buf.len,
2868 switch (std.os.errno(rc)) {2873 }};
2869 .SUCCESS => assert(rc == buf.len),2874 const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0);
2870 else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),2875 switch (std.os.errno(rc)) {
2876 .SUCCESS => assert(rc == buf.len),
2877 else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
2878 }
2879 },
2880 else => return error.HotSwapUnavailableOnHostOperatingSystem,
2871 }2881 }
2872 }2882 }
2873 },2883 },
src/main.zig+3-3
...@@ -3534,7 +3534,7 @@ fn serve(...@@ -3534,7 +3534,7 @@ fn serve(
35343534
3535 try serveStringMessage(out, .zig_version, build_options.version);3535 try serveStringMessage(out, .zig_version, build_options.version);
35363536
3537 var child_pid: ?i32 = null;3537 var child_pid: ?std.ChildProcess.Id = null;
3538 var receive_fifo = std.fifo.LinearFifo(u8, .Dynamic).init(gpa);3538 var receive_fifo = std.fifo.LinearFifo(u8, .Dynamic).init(gpa);
3539 defer receive_fifo.deinit();3539 defer receive_fifo.deinit();
35403540
...@@ -3978,7 +3978,7 @@ fn runOrTestHotSwap(...@@ -3978,7 +3978,7 @@ fn runOrTestHotSwap(
3978 arg_mode: ArgMode,3978 arg_mode: ArgMode,
3979 all_args: []const []const u8,3979 all_args: []const []const u8,
3980 runtime_args_start: ?usize,3980 runtime_args_start: ?usize,
3981) !i32 {3981) !std.ChildProcess.Id {
3982 const exe_emit = comp.bin_file.options.emit.?;3982 const exe_emit = comp.bin_file.options.emit.?;
3983 // A naive `directory.join` here will indeed get the correct path to the binary,3983 // A naive `directory.join` here will indeed get the correct path to the binary,
3984 // however, in the case of cwd, we actually want `./foo` so that the path can be executed.3984 // however, in the case of cwd, we actually want `./foo` so that the path can be executed.
...@@ -4023,7 +4023,7 @@ fn runOrTestHotSwap(...@@ -4023,7 +4023,7 @@ fn runOrTestHotSwap(
40234023
4024 try child.spawn();4024 try child.spawn();
40254025
4026 return child.pid;4026 return child.id;
4027}4027}
40284028
4029const AfterUpdateHook = union(enum) {4029const AfterUpdateHook = union(enum) {
src/test.zig+1-2
...@@ -1606,9 +1606,8 @@ pub const TestContext = struct {...@@ -1606,9 +1606,8 @@ pub const TestContext = struct {
16061606
1607 var module_node = update_node.start("parse/analysis/codegen", 0);1607 var module_node = update_node.start("parse/analysis/codegen", 0);
1608 module_node.activate();1608 module_node.activate();
1609 module_node.context.refresh();
1610 try comp.makeBinFileWritable();1609 try comp.makeBinFileWritable();
1611 try comp.update();1610 try comp.update(&module_node);
1612 module_node.end();1611 module_node.end();
16131612
1614 if (update.case != .Error) {1613 if (update.case != .Error) {