Commit 9bf63b0996

Andrew Kelley <andrew@ziglang.org>
2023-03-03 06:37:07
stage2: avoid linux-only APIs on other operating systems
1 parent 7ffdbb3
src/link/Elf.zig
@@ -2453,18 +2453,23 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
     const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset;
 
     if (self.base.child_pid) |pid| {
-        var code_vec: [1]std.os.iovec_const = .{.{
-            .iov_base = code.ptr,
-            .iov_len = code.len,
-        }};
-        var remote_vec: [1]std.os.iovec_const = .{.{
-            .iov_base = @intToPtr([*]u8, local_sym.st_value),
-            .iov_len = code.len,
-        }};
-        const rc = std.os.linux.process_vm_writev(pid, &code_vec, &remote_vec, 0);
-        switch (std.os.errno(rc)) {
-            .SUCCESS => assert(rc == code.len),
-            else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
+        switch (builtin.os.tag) {
+            .linux => {
+                var code_vec: [1]std.os.iovec_const = .{.{
+                    .iov_base = code.ptr,
+                    .iov_len = code.len,
+                }};
+                var remote_vec: [1]std.os.iovec_const = .{.{
+                    .iov_base = @intToPtr([*]u8, local_sym.st_value),
+                    .iov_len = code.len,
+                }};
+                const rc = std.os.linux.process_vm_writev(pid, &code_vec, &remote_vec, 0);
+                switch (std.os.errno(rc)) {
+                    .SUCCESS => assert(rc == code.len),
+                    else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
+                }
+            },
+            else => return error.HotSwapUnavailableOnHostOperatingSystem,
         }
     }
 
@@ -2856,18 +2861,23 @@ fn writeOffsetTableEntry(self: *Elf, index: usize) !void {
             try self.base.file.?.pwriteAll(&buf, off);
 
             if (self.base.child_pid) |pid| {
-                var local_vec: [1]std.os.iovec_const = .{.{
-                    .iov_base = &buf,
-                    .iov_len = buf.len,
-                }};
-                var remote_vec: [1]std.os.iovec_const = .{.{
-                    .iov_base = @intToPtr([*]u8, vaddr),
-                    .iov_len = buf.len,
-                }};
-                const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0);
-                switch (std.os.errno(rc)) {
-                    .SUCCESS => assert(rc == buf.len),
-                    else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
+                switch (builtin.os.tag) {
+                    .linux => {
+                        var local_vec: [1]std.os.iovec_const = .{.{
+                            .iov_base = &buf,
+                            .iov_len = buf.len,
+                        }};
+                        var remote_vec: [1]std.os.iovec_const = .{.{
+                            .iov_base = @intToPtr([*]u8, vaddr),
+                            .iov_len = buf.len,
+                        }};
+                        const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0);
+                        switch (std.os.errno(rc)) {
+                            .SUCCESS => assert(rc == buf.len),
+                            else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
+                        }
+                    },
+                    else => return error.HotSwapUnavailableOnHostOperatingSystem,
                 }
             }
         },
src/Compilation.zig
@@ -1847,7 +1847,7 @@ fn cleanupTmpArtifactDirectory(
     }
 }
 
-pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.os.pid_t) !void {
+pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.ChildProcess.Id) !void {
     comp.bin_file.child_pid = pid;
     try comp.makeBinFileWritable();
     try comp.update(prog_node);
src/link.zig
@@ -264,7 +264,7 @@ pub const File = struct {
     /// of this linking operation.
     lock: ?Cache.Lock = null,
 
-    child_pid: ?std.os.pid_t = null,
+    child_pid: ?std.ChildProcess.Id = null,
 
     /// Attempts incremental linking, if the file already exists. If
     /// incremental linking fails, falls back to truncating the file and
@@ -388,10 +388,14 @@ pub const File = struct {
                     });
                     try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, tmp_sub_path, .{});
                     try emit.directory.handle.rename(tmp_sub_path, emit.sub_path);
-
-                    switch (std.os.errno(std.os.linux.ptrace(std.os.linux.PTRACE.ATTACH, pid, 0, 0, 0))) {
-                        .SUCCESS => {},
-                        else => |errno| log.warn("ptrace failure: {s}", .{@tagName(errno)}),
+                    switch (builtin.os.tag) {
+                        .linux => {
+                            switch (std.os.errno(std.os.linux.ptrace(std.os.linux.PTRACE.ATTACH, pid, 0, 0, 0))) {
+                                .SUCCESS => {},
+                                else => |errno| log.warn("ptrace failure: {s}", .{@tagName(errno)}),
+                            }
+                        },
+                        else => return error.HotSwapUnavailableOnHostOperatingSystem,
                     }
                 }
                 base.file = try emit.directory.handle.createFile(emit.sub_path, .{
@@ -444,9 +448,14 @@ pub const File = struct {
                 base.file = null;
 
                 if (base.child_pid) |pid| {
-                    switch (std.os.errno(std.os.linux.ptrace(std.os.linux.PTRACE.DETACH, pid, 0, 0, 0))) {
-                        .SUCCESS => {},
-                        else => |errno| log.warn("ptrace failure: {s}", .{@tagName(errno)}),
+                    switch (builtin.os.tag) {
+                        .linux => {
+                            switch (std.os.errno(std.os.linux.ptrace(std.os.linux.PTRACE.DETACH, pid, 0, 0, 0))) {
+                                .SUCCESS => {},
+                                else => |errno| log.warn("ptrace failure: {s}", .{@tagName(errno)}),
+                            }
+                        },
+                        else => return error.HotSwapUnavailableOnHostOperatingSystem,
                     }
                 }
             },
@@ -487,6 +496,7 @@ pub const File = struct {
         NetNameDeleted,
         DeviceBusy,
         InvalidArgument,
+        HotSwapUnavailableOnHostOperatingSystem,
     };
 
     /// Called from within the CodeGen to lower a local variable instantion as an unnamed
src/main.zig
@@ -3534,7 +3534,7 @@ fn serve(
 
     try serveStringMessage(out, .zig_version, build_options.version);
 
-    var child_pid: ?i32 = null;
+    var child_pid: ?std.ChildProcess.Id = null;
     var receive_fifo = std.fifo.LinearFifo(u8, .Dynamic).init(gpa);
     defer receive_fifo.deinit();
 
@@ -3978,7 +3978,7 @@ fn runOrTestHotSwap(
     arg_mode: ArgMode,
     all_args: []const []const u8,
     runtime_args_start: ?usize,
-) !i32 {
+) !std.ChildProcess.Id {
     const exe_emit = comp.bin_file.options.emit.?;
     // A naive `directory.join` here will indeed get the correct path to the binary,
     // however, in the case of cwd, we actually want `./foo` so that the path can be executed.
@@ -4023,7 +4023,7 @@ fn runOrTestHotSwap(
 
     try child.spawn();
 
-    return child.pid;
+    return child.id;
 }
 
 const AfterUpdateHook = union(enum) {
src/test.zig
@@ -1606,9 +1606,8 @@ pub const TestContext = struct {
 
             var module_node = update_node.start("parse/analysis/codegen", 0);
             module_node.activate();
-            module_node.context.refresh();
             try comp.makeBinFileWritable();
-            try comp.update();
+            try comp.update(&module_node);
             module_node.end();
 
             if (update.case != .Error) {