Commit 4164523

Pavel Borzenkov  ·  2026-04-24 11:37:27 -0400 EDT
parent 6feca74
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
......@@ -560,6 +560,14 @@ const Daemon = struct {
560560
561561 pub fn closeClient(self: *Daemon, client: *Client, i: usize, shutdown_on_last: bool) bool {
562562 const fd = client.socket_fd;
563+ // leader is disconnected, remove ref and let another client claim leader on input
564+ if (self.leader_client_fd == client.socket_fd) {
565+ std.log.info(
566+ "unsetting leader session={s} fd={d}",
567+ .{ self.session_name, client.socket_fd },
568+ );
569+ self.leader_client_fd = null;
570+ }
563571 client.deinit();
564572 self.alloc.destroy(client);
565573 _ = self.clients.orderedRemove(i);
......@@ -961,14 +969,6 @@ const Daemon = struct {
961969
962970 pub fn handleDetach(self: *Daemon, client: *Client, i: usize) void {
963971 std.log.info("client detach session={s} fd={d}", .{ self.session_name, client.socket_fd });
964- // leader is trying to disconnect, remove ref and let another client claim leader on input
965- if (self.leader_client_fd == client.socket_fd) {
966- std.log.info(
967- "unsetting leader session={s} fd={d}",
968- .{ self.session_name, client.socket_fd },
969- );
970- self.leader_client_fd = null;
971- }
972972 _ = self.closeClient(client, i, false);
973973 }
974974