| author | |
| committer | |
| log | 9bf63b09963ca6ea1179dfaa9142498556bfac9d |
| tree | 61bc3e7308c21eb2dab6432a358be97e896edb1b |
| parent | 7ffdbb3b855ef9e4aa25a8ac911fce752a71e16d |
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 | } |
| 1849 | 1849 | ||
| 1850 | pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.os.pid_t) !void { | 1850 | pub 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, |
| 266 | 266 | ||
| 267 | child_pid: ?std.os.pid_t = null, | 267 | child_pid: ?std.ChildProcess.Id = null, |
| 268 | 268 | ||
| 269 | /// Attempts incremental linking, if the file already exists. If | 269 | /// Attempts incremental linking, if the file already exists. If |
| 270 | /// incremental linking fails, falls back to truncating the file and | 270 | /// 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); |
| 391 | 391 | 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; |
| 445 | 449 | ||
| 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 | }; |
| 491 | 501 | ||
| 492 | /// Called from within the CodeGen to lower a local variable instantion as an unnamed | 502 | /// 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; |
| 2454 | 2454 | ||
| 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 | } |
| 2470 | 2475 | ||
| ... | @@ -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); |
| 2857 | 2862 | ||
| 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( |
| 3534 | 3534 | ||
| 3535 | try serveStringMessage(out, .zig_version, build_options.version); | 3535 | try serveStringMessage(out, .zig_version, build_options.version); |
| 3536 | 3536 | ||
| 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(); |
| 3540 | 3540 | ||
| ... | @@ -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( |
| 4023 | 4023 | ||
| 4024 | try child.spawn(); | 4024 | try child.spawn(); |
| 4025 | 4025 | ||
| 4026 | return child.pid; | 4026 | return child.id; |
| 4027 | } | 4027 | } |
| 4028 | 4028 | ||
| 4029 | const AfterUpdateHook = union(enum) { | 4029 | const AfterUpdateHook = union(enum) { |
src/test.zig+1-2| ... | @@ -1606,9 +1606,8 @@ pub const TestContext = struct { | ... | @@ -1606,9 +1606,8 @@ pub const TestContext = struct { |
| 1606 | 1606 | ||
| 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(); |
| 1613 | 1612 | ||
| 1614 | if (update.case != .Error) { | 1613 | if (update.case != .Error) { |