- commit
- 4164523
- parent
- 6feca74
- author
- Pavel Borzenkov
- date
- 2026-04-24 11:37:27 -0400 EDT
fix(daemon): reset leader fd on client disconnect (#141)
Make sure leader fd is reset when the leader client disconnects abruptly
without going through 'Detach' IPC. Otherwise, the daemon may remember
wrong client fd as the leader and run all input from the client via
libghostty parser.
Fixes #135
NOTE: this currently doesn't address the issue when libghostty can't
parse the byte sequence and complains like this:
[warning] (parser): CSI colon or mixed separators only allowed for 'm'
command, got: terminal.Parser.Action{ .csi_dispatch = .{ .intermediates
= { }, .params = { 57444, 1, 1 }, .params_sep = .{ .mask = 2 }, .final
= 117 } }
1 files changed,
+8,
-8
+8,
-8
1@@ -560,6 +560,14 @@ const Daemon = struct {
2
3 pub fn closeClient(self: *Daemon, client: *Client, i: usize, shutdown_on_last: bool) bool {
4 const fd = client.socket_fd;
5+ // leader is disconnected, remove ref and let another client claim leader on input
6+ if (self.leader_client_fd == client.socket_fd) {
7+ std.log.info(
8+ "unsetting leader session={s} fd={d}",
9+ .{ self.session_name, client.socket_fd },
10+ );
11+ self.leader_client_fd = null;
12+ }
13 client.deinit();
14 self.alloc.destroy(client);
15 _ = self.clients.orderedRemove(i);
16@@ -961,14 +969,6 @@ const Daemon = struct {
17
18 pub fn handleDetach(self: *Daemon, client: *Client, i: usize) void {
19 std.log.info("client detach session={s} fd={d}", .{ self.session_name, client.socket_fd });
20- // leader is trying to disconnect, remove ref and let another client claim leader on input
21- if (self.leader_client_fd == client.socket_fd) {
22- std.log.info(
23- "unsetting leader session={s} fd={d}",
24- .{ self.session_name, client.socket_fd },
25- );
26- self.leader_client_fd = null;
27- }
28 _ = self.closeClient(client, i, false);
29 }
30