diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fs.zig | 30 |
1 files changed, 29 insertions, 1 deletions
@@ -693,7 +693,17 @@ pub fn Server(comptime Backend: type, comptime opts: Options) type { return null; } const sl = &s.slots[i]; - if (sl.holdsJob()) return s.resumeJob(i); + if (sl.holdsJob()) { + // Its fid may have been clunked while it waited: then there + // is nobody to answer, and asking the backend would make it + // do the work -- open a handle, make an object -- for no one. + if (s.findFid(sl.fid) == null) { + s.fail(sl.tag, e_unknown_fid); + sl.* = .{}; + return s.retry(); + } + return s.resumeJob(i); + } sl.retried = true; sl.parked = false; return sl.req; @@ -2221,6 +2231,24 @@ test "fs server: a parked open, truncate and clunk complete on retry, and a walk try testing.expectEqualStrings(e_again, got.msg.rerror.ename); h.fsys.park_lookups = false; + // A parked open whose fid is clunked meanwhile is answered for the + // clunk's sake and never asked again: the backend would otherwise open + // a handle for nobody. + _ = try h.walkTo(16, 5, &.{ "1", "tag" }); + h.fsys.park_opens = true; + try h.send(17, .{ .topen = .{ .fid = 5, .mode = oread } }); + try h.quiet(); + try h.send(18, .{ .tclunk = .{ .fid = 5 } }); + got = try h.reap(); + try testing.expect(got.msg == .rclunk); + h.fsys.park_opens = false; + const asked = h.fsys.calls; + h.pump(); + got = try h.reap(); + try testing.expectEqual(@as(u16, 17), got.tag); + try testing.expectEqualStrings(e_unknown_fid, got.msg.rerror.ename); + try testing.expectEqual(asked, h.fsys.calls); + // A flush reaches a parked job the way it reaches a parked read. h.fsys.park_opens = true; try h.send(14, .{ .topen = .{ .fid = 2, .mode = oread } }); |
