Skip to content

Commit ac51a49

Browse files
committed
fix fork cache bug in MemoryAccessor.zig
1 parent 7c709f9 commit ac51a49

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

lib/std/debug/MemoryAccessor.zig

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ pub fn deinit(ma: *MemoryAccessor) void {
3838

3939
fn read(ma: *MemoryAccessor, address: usize, buf: []u8) bool {
4040
switch (native_os) {
41-
.linux => while (true) switch (ma.mem.handle) {
42-
-2 => break,
41+
.linux => linux: switch (ma.mem.handle) {
42+
-2 => break :linux,
4343
-1 => {
4444
const linux = std.os.linux;
4545
const pid = switch (@atomicLoad(posix.pid_t, &cached_pid, .monotonic)) {
@@ -59,7 +59,15 @@ fn read(ma: *MemoryAccessor, address: usize, buf: []u8) bool {
5959
switch (linux.E.init(bytes_read)) {
6060
.SUCCESS => return bytes_read == buf.len,
6161
.FAULT => return false,
62-
.INVAL, .SRCH => unreachable, // own pid is always valid
62+
.INVAL => unreachable, // EINVAL is returned when flags to process_vm_readv is non-zero
63+
.SRCH => {
64+
// process with pid does not exist, but it should be our pid, so we'll try again.
65+
// This can happen after a call to fork() without a corresponding exec()
66+
const newpid = linux.getpid();
67+
std.debug.assert(newpid != pid);
68+
@atomicStore(posix.pid_t, &cached_pid, newpid, .monotonic);
69+
continue :linux -1;
70+
},
6371
.PERM => {}, // Known to happen in containers.
6472
.NOMEM => {},
6573
.NOSYS => {}, // QEMU is known not to implement this syscall.
@@ -72,7 +80,7 @@ fn read(ma: *MemoryAccessor, address: usize, buf: []u8) bool {
7280
unreachable;
7381
ma.mem = std.fs.openFileAbsolute(path, .{}) catch {
7482
ma.mem.handle = -2;
75-
break;
83+
break :linux;
7684
};
7785
},
7886
else => return (ma.mem.pread(buf, address) catch return false) == buf.len,

0 commit comments

Comments
 (0)