aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPeter Geissler <peter@haxx.in>2026-08-26 16:44:33 +0200
committeruser <user@clank>2026-08-26 16:48:17 +0200
commit9d5f9d2a1c3b8d0948a8efa8443a36847aa2107b (patch)
treec56a344009a59970d1e0495ec76568ebf6046275 /include
parentmacos: the kernel still knows, it just spells /proc differently (diff)
downloadslosh-9d5f9d2a1c3b8d0948a8efa8443a36847aa2107b.tar.gz
slosh-9d5f9d2a1c3b8d0948a8efa8443a36847aa2107b.tar.xz
slosh-9d5f9d2a1c3b8d0948a8efa8443a36847aa2107b.zip
a client that stops reading must not stop the session
Everything the server said went out through msg_send(), which loops on sendmsg() until the kernel has taken all of it. That is a blocking write to whoever is attached. A display whose reader has paused -- C-s at the terminal, a stopped ssh, a client being swapped -- fills its socket buffer, and then the *server* sits inside that loop: every other pane, the config watcher, the control socket and every other connection stop with it. A session that is supposed to outlive its client hangs on one. macOS is where this showed up, because its socket buffers are a fraction of Linux's 64K and it wedges within a screenful rather than after a few hundred. `make test-live` could not get past the forty-connection probe in test_session.py: the server was blocked writing to a pty nobody was draining, so `slosh cmd panes` timed out and took the suite with it. So connections are non-blocking and output is queued, flushed when poll() says the socket will take more. The queue is capped: past 4MB we are not buffering a slow reader any more, we are storing a screen nobody is looking at, and the connection is dropped -- a display that comes back reattaches and gets a full repaint, which is what happens after any detach anyway. Measured, with a pane running `yes` and a display that never reads: before, the first control command hung forever; after, 40 of 40 are answered, the session stays listed, and the server's RSS is flat.
Diffstat (limited to 'include')
-rw-r--r--include/proto.h8
1 files changed, 7 insertions, 1 deletions
diff --git a/include/proto.h b/include/proto.h
index e6cd42c..67b45f0 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -54,7 +54,13 @@ void msg_reader_feed(msg_reader_t *r, const uint8_t *data, size_t len);
* until the next call) when a whole message is available. */
bool msg_reader_next(msg_reader_t *r, msg_t *out);
-/* Blocking send of one frame. Returns 0 on success, -1 if the peer is gone. */
+/* One frame is a type byte and a 32-bit big-endian length, then the payload.
+ * The server frames into its own queue (it cannot afford to block on a client
+ * that has stopped reading), so the size is not private to proto.c. */
+#define MSG_HDR 5
+
+/* Blocking send of one frame. Returns 0 on success, -1 if the peer is gone.
+ * For the client, which has nothing else to be doing while it writes. */
int msg_send(int fd, uint8_t type, const void *data, size_t len);
/* $XDG_RUNTIME_DIR/slosh/<name>.sock, or /tmp/slosh-<uid>/<name>.sock.