summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 10:58:58 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit6add2ee79879712b39f6f76165a24a641127dd3b (patch)
treefe8ea592e8f6e6642a81cbfbe70b3b2527b5f3f0 /src
parent2a71bff5f06ba3e785a5eb96a8377e2cab8e2cdd (diff)
downloadpardes-6add2ee79879712b39f6f76165a24a641127dd3b.tar.gz
pardes-6add2ee79879712b39f6f76165a24a641127dd3b.zip
Kill written to /ctl is answered before the editor quits
The write got EPIPE: Kill set quit, the request waited for the editor to settle its effects, and the editor quit and cut the connections first. A write that quits the editor is now answered at once, and the listener lets pending answers out (up to 200 ms) before it stops the runner. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/9p_io.zig19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/9p_io.zig b/src/9p_io.zig
index 02b9efb5..d6eef9d4 100644
--- a/src/9p_io.zig
+++ b/src/9p_io.zig
@@ -262,6 +262,10 @@ pub const Listener = struct {
// buffer for it, which a request run while this one waited would
// write over.
if (reply.status == .err) return conn.reply(&reply, "");
+ // A write that quits the editor (Kill) is answered now: the editor
+ // is on its way out and will settle nothing this could wait for,
+ // and `deinit` lets the answer out before it cuts the connections.
+ if (core.quit) return conn.reply(&reply, "");
const restoring = core.restore_req != null;
if (core.effects_len != 0) pardes.turn.awaitSettled(epoch);
// Once a wait returns `core` may be gone: a Restore meanwhile put a
@@ -698,6 +702,21 @@ pub const Listener = struct {
// A connection task may be waiting for the turn; it answers
// nothing more once stopping, but the wait itself must end.
pardes.turn.rest();
+ // An answer given as the editor quit (a Kill written to /ctl)
+ // may still be on its way out: let it go before the cut.
+ const deadline = nowMs() +| 200;
+ while (nowMs() < deadline) {
+ const pending = for (&l.runner.conns) |*conn| {
+ if (!conn.live()) continue;
+ conn.lock();
+ const n = conn.engine.output().len;
+ conn.unlock();
+ if (n != 0) break true;
+ } else false;
+ if (!pending) break;
+ Client.nap(1);
+ }
+ Client.nap(1); // the last bytes leave the stream's own buffer
l.runner.stop();
pardes.turn.wake();
}