From ed2b349c3e5057e446fb5adab398f80ef1050d4e Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 22 Sep 2026 06:46:50 +0000 Subject: [PATCH] Do not leak waiting clients (in wait-for) if they are killed, GitHub issue 5614. --- cmd-queue.c | 5 ++++- cmd-wait-for.c | 36 +++++++++++++++++++++++++++++++++++- server-client.c | 5 ++++- tmux.h | 3 ++- 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/cmd-queue.c b/cmd-queue.c index a9ce469bc..e84c265f7 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-queue.c,v 1.123 2026/08/24 20:34:26 nicm Exp $ */ +/* $OpenBSD: cmd-queue.c,v 1.124 2026/09/22 06:46:50 nicm Exp $ */ /* * Copyright (c) 2013 Nicholas Marriott @@ -580,6 +580,9 @@ cmdq_fire_command(struct cmdq_item *item) int flags, quiet = 0; char *tmp; + if (item->client != NULL && (item->client->flags & CLIENT_DEAD)) + return (CMD_RETURN_ERROR); + if (cfg_finished) cmdq_add_message(item); if (log_get_level() > 1) { diff --git a/cmd-wait-for.c b/cmd-wait-for.c index 0e4130fcd..7326c7519 100644 --- a/cmd-wait-for.c +++ b/cmd-wait-for.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-wait-for.c,v 1.23 2026/07/10 13:38:45 nicm Exp $ */ +/* $OpenBSD: cmd-wait-for.c,v 1.24 2026/09/22 06:46:50 nicm Exp $ */ /* * Copyright (c) 2013 Nicholas Marriott @@ -480,6 +480,40 @@ cmd_wait_for_unlock(struct cmdq_item *item, const char *name, return (CMD_RETURN_NORMAL); } +void +cmd_wait_for_client_lost(struct client *c) +{ + struct wait_channel *wc, *wc1; + struct wait_item *wi, *wi1; + struct wait_event_item *wei, *wei1; + + TAILQ_FOREACH_SAFE(wei, &wait_event_items, entry, wei1) { + if (cmdq_get_client(wei->item) == c) { + TAILQ_REMOVE(&wait_event_items, wei, entry); + cmdq_continue(wei->item); + cmd_wait_for_event_free(wei); + } + } + + RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) { + TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) { + if (cmdq_get_client(wi->item) == c) { + cmdq_continue(wi->item); + TAILQ_REMOVE(&wc->waiters, wi, entry); + free(wi); + } + } + TAILQ_FOREACH_SAFE(wi, &wc->lockers, entry, wi1) { + if (cmdq_get_client(wi->item) == c) { + cmdq_continue(wi->item); + TAILQ_REMOVE(&wc->lockers, wi, entry); + free(wi); + } + } + cmd_wait_for_remove_empty(wc); + } +} + void cmd_wait_for_flush(void) { diff --git a/server-client.c b/server-client.c index 6aa0b562b..369e6d223 100644 --- a/server-client.c +++ b/server-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server-client.c,v 1.512 2026/09/10 11:02:18 nicm Exp $ */ +/* $OpenBSD: server-client.c,v 1.514 2026/09/22 06:46:50 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -502,6 +502,9 @@ server_client_lost(struct client *c) TAILQ_REMOVE(&clients, c, entry); log_debug("lost client %p", c); + cmd_wait_for_client_lost(c); + cmdq_next(c); + if (c->flags & CLIENT_ATTACHED) { server_client_attached_lost(c); events_fire_client("client-detached", c); diff --git a/tmux.h b/tmux.h index e9dffc814..21262af2f 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1443 2026/09/21 10:33:16 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1445 2026/09/22 06:46:50 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -3227,6 +3227,7 @@ void cmdq_print_data(struct cmdq_item *, struct evbuffer *); void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...); /* cmd-wait-for.c */ +void cmd_wait_for_client_lost(struct client *); void cmd_wait_for_flush(void); /* client.c */