seatd: deliver the enable event sent while opening a seat

seatd answers CLIENT_OPEN_SEAT by buffering the response and the enable
event together, so both reach libseat in one read. libseat parses only
the response and leaves the event in its connection buffer, with nothing
left on the socket for a client watching the fd to be woken by, so a
client that follows the documented contract never activates its seat.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
Daniel Golle committed 2026-10-03 16:57:13 +01:00
1 parent 656818e12b
commit 90b4a43150
2 files changed
+41 -1

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=seatd
PKG_VERSION:=0.9.3
PKG_RELEASE:=2
PKG_RELEASE:=3
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://git.sr.ht/~kennylevinsen/seatd
@@ -0,0 +1,40 @@
From 4c8c6046a8dba6dd5ab4b60a62cb5abe3aefa5d2 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Thu, 1 Oct 2026 14:49:22 +0100
Subject: [PATCH] libseat/seatd: drain events queued while opening the seat
seatd answers CLIENT_OPEN_SEAT by buffering SERVER_SEAT_OPENED and then
calling seat_open_client(), which buffers SERVER_ENABLE_SEAT, so both
messages reach the client in a single read. read_and_queue() stops at
the first non-event header, restores it and returns, which leaves the
enable event unparsed in the connection buffer. _open_seat() consumes
only the response and then calls execute_events() on an empty queue.
Nothing is left on the socket at that point, so a client that dispatches
when its fd becomes readable, as the documented contract invites, never
sees the event and never activates its seat. Read and queue once more
before executing, so an event delivered alongside the response is
handled during open.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
libseat/backend/seatd.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/libseat/backend/seatd.c
+++ b/libseat/backend/seatd.c
@@ -432,6 +432,14 @@ static struct libseat *_open_seat(const
goto backend_error;
}
+ // The server flushes the enable event together with the open response,
+ // so it is likely already sitting in our connection buffer with
+ // nothing left on the socket to wake a poll on our fd.
+ if (read_and_queue(backend, NULL) == -1) {
+ res = -errno;
+ goto backend_error;
+ }
+
execute_events(backend);
return &backend->base;