mirror of
https://github.com/tmux/tmux.git
synced 2026-10-09 19:54:22 +00:00
Do not attempt to drain write buffer on stuck clients, since it requires
a weird dance to make libevent do it. Instead, just ignore the client and destroy the buffer normally if not drained in 10 seconds.
This commit is contained in:
10
control.c
10
control.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: control.c,v 1.64 2026/08/03 20:18:20 nicm Exp $ */
|
/* $OpenBSD: control.c,v 1.65 2026/08/04 11:18:22 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -968,21 +968,17 @@ control_discard(struct client *c)
|
|||||||
bufferevent_disable(cs->read_event, EV_READ);
|
bufferevent_disable(cs->read_event, EV_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Discard all tmux-owned queued control blocks and stop writing. */
|
||||||
* Discard all output for a client, including output which has already been
|
|
||||||
* queued to be written.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
control_discard_all(struct client *c)
|
control_discard_all(struct client *c)
|
||||||
{
|
{
|
||||||
struct control_state *cs = c->control_state;
|
struct control_state *cs = c->control_state;
|
||||||
struct control_block *cb, *cb1;
|
struct control_block *cb, *cb1;
|
||||||
struct evbuffer *evb = cs->write_event->output;
|
|
||||||
|
|
||||||
control_discard(c);
|
control_discard(c);
|
||||||
TAILQ_FOREACH_SAFE(cb, &cs->all_blocks, all_entry, cb1)
|
TAILQ_FOREACH_SAFE(cb, &cs->all_blocks, all_entry, cb1)
|
||||||
control_free_block(cs, cb);
|
control_free_block(cs, cb);
|
||||||
evbuffer_drain(evb, EVBUFFER_LENGTH(evb));
|
bufferevent_disable(cs->write_event, EV_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stop control mode. */
|
/* Stop control mode. */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: server-client.c,v 1.501 2026/08/03 20:18:20 nicm Exp $ */
|
/* $OpenBSD: server-client.c,v 1.502 2026/08/04 11:18:22 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -41,7 +41,7 @@ static void server_client_check_window_resize(struct window *);
|
|||||||
static key_code server_client_check_mouse(struct client *, struct key_event *);
|
static key_code server_client_check_mouse(struct client *, struct key_event *);
|
||||||
static void server_client_repeat_timer(int, short, void *);
|
static void server_client_repeat_timer(int, short, void *);
|
||||||
static void server_client_click_timer(int, short, void *);
|
static void server_client_click_timer(int, short, void *);
|
||||||
static void server_client_check_exit(struct client *);
|
static void server_client_check_exit(struct client *, int);
|
||||||
static void server_client_exit_timer(int, short, void *);
|
static void server_client_exit_timer(int, short, void *);
|
||||||
static void server_client_check_redraw(struct client *);
|
static void server_client_check_redraw(struct client *);
|
||||||
static void server_client_check_modes(struct client *);
|
static void server_client_check_modes(struct client *);
|
||||||
@@ -1857,7 +1857,7 @@ server_client_loop(void)
|
|||||||
|
|
||||||
/* Check clients. */
|
/* Check clients. */
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
server_client_check_exit(c);
|
server_client_check_exit(c, 0);
|
||||||
if (c->session != NULL && c->session->curw != NULL) {
|
if (c->session != NULL && c->session->curw != NULL) {
|
||||||
server_client_check_modes(c);
|
server_client_check_modes(c);
|
||||||
server_client_check_redraw(c);
|
server_client_check_redraw(c);
|
||||||
@@ -2307,8 +2307,7 @@ server_client_start_exit_timer(struct client *c)
|
|||||||
static void
|
static void
|
||||||
server_client_exit_timer(__unused int fd, __unused short events, void *data)
|
server_client_exit_timer(__unused int fd, __unused short events, void *data)
|
||||||
{
|
{
|
||||||
struct client *c = data;
|
struct client *c = data;
|
||||||
struct client_file *cf;
|
|
||||||
|
|
||||||
if (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED))
|
if (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED))
|
||||||
return;
|
return;
|
||||||
@@ -2318,17 +2317,13 @@ server_client_exit_timer(__unused int fd, __unused short events, void *data)
|
|||||||
server_client_lost(c);
|
server_client_lost(c);
|
||||||
} else if (c->flags & CLIENT_EXIT) {
|
} else if (c->flags & CLIENT_EXIT) {
|
||||||
log_debug("%s: %s took too long to flush", __func__, c->name);
|
log_debug("%s: %s took too long to flush", __func__, c->name);
|
||||||
if (c->flags & CLIENT_CONTROL)
|
server_client_check_exit(c, 1);
|
||||||
control_discard_all(c);
|
|
||||||
RB_FOREACH(cf, client_files, &c->files)
|
|
||||||
evbuffer_drain(cf->buffer, EVBUFFER_LENGTH(cf->buffer));
|
|
||||||
server_client_check_exit(c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if client should be exited. */
|
/* Check if client should be exited, abandoning buffered output if forced. */
|
||||||
static void
|
static void
|
||||||
server_client_check_exit(struct client *c)
|
server_client_check_exit(struct client *c, int force)
|
||||||
{
|
{
|
||||||
struct client_file *cf;
|
struct client_file *cf;
|
||||||
const char *name = c->exit_session;
|
const char *name = c->exit_session;
|
||||||
@@ -2341,16 +2336,22 @@ server_client_check_exit(struct client *c)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (c->flags & CLIENT_CONTROL) {
|
if (c->flags & CLIENT_CONTROL) {
|
||||||
control_discard(c);
|
if (force)
|
||||||
if (!control_all_done(c)) {
|
control_discard_all(c);
|
||||||
server_client_start_exit_timer(c);
|
else {
|
||||||
return;
|
control_discard(c);
|
||||||
|
if (!control_all_done(c)) {
|
||||||
|
server_client_start_exit_timer(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RB_FOREACH(cf, client_files, &c->files) {
|
if (!force) {
|
||||||
if (EVBUFFER_LENGTH(cf->buffer) != 0) {
|
RB_FOREACH(cf, client_files, &c->files) {
|
||||||
server_client_start_exit_timer(c);
|
if (EVBUFFER_LENGTH(cf->buffer) != 0) {
|
||||||
return;
|
server_client_start_exit_timer(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c->flags |= CLIENT_EXITED;
|
c->flags |= CLIENT_EXITED;
|
||||||
|
|||||||
Reference in New Issue
Block a user