summaryrefslogtreecommitdiffstats
path: root/server-client.c
diff options
context:
space:
mode:
authornicm <nicm>2020-06-01 09:43:00 +0000
committernicm <nicm>2020-06-01 09:43:00 +0000
commita54a88edd6fd893d4370feb9f9136e13096b891c (patch)
tree1e42bf42d42c31e1ef3c059aaf1ae25ae6ef3bd5 /server-client.c
parent175e45005f4572b19a4aa34094f9a8c69ced5475 (diff)
Instead of sending all data to control mode clients as fast as possible,
add a limit of how much data will be sent to the client and try to use it for panes with some degree of fairness. GitHub issue 2217, with George Nachman.
Diffstat (limited to 'server-client.c')
-rw-r--r--server-client.c82
1 files changed, 50 insertions, 32 deletions
diff --git a/server-client.c b/server-client.c
index d4fa92dc..5218340e 100644
--- a/server-client.c
+++ b/server-client.c
@@ -58,6 +58,9 @@ static void server_client_dispatch_read_data(struct client *,
static void server_client_dispatch_read_done(struct client *,
struct imsg *);
+/* Maximum data allowed to be held for a pane for a control client. */
+#define SERVER_CLIENT_PANE_LIMIT 16777216
+
/* Compare client windows. */
static int
server_client_window_cmp(struct client_window *cw1,
@@ -80,7 +83,7 @@ server_client_how_many(void)
n = 0;
TAILQ_FOREACH(c, &clients, entry) {
- if (c->session != NULL && (~c->flags & CLIENT_DETACHING))
+ if (c->session != NULL && (~c->flags & CLIENT_UNATTACHEDFLAGS))
n++;
}
return (n);
@@ -386,7 +389,7 @@ server_client_suspend(struct client *c)
{
struct session *s = c->session;
- if (s == NULL || (c->flags & CLIENT_DETACHING))
+ if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
return;
tty_stop_tty(&c->tty);
@@ -400,12 +403,14 @@ server_client_detach(struct client *c, enum msgtype msgtype)
{
struct session *s = c->session;
- if (s == NULL || (c->flags & CLIENT_DETACHING))
+ if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
return;
- c->flags |= CLIENT_DETACHING;
- notify_client("client-detached", c);
- proc_send(c->peer, msgtype, -1, s->name, strlen(s->name) + 1);
+ c->flags |= CLIENT_EXIT;
+
+ c->exit_type = CLIENT_EXIT_DETACH;
+ c->exit_msgtype = msgtype;
+ c->exit_session = xstrdup(s->name);
}
/* Execute command to replace a client. */
@@ -1507,12 +1512,12 @@ server_client_check_pane_buffer(struct window_pane *wp)
u_int attached_clients = 0;
/*
- * Work out the minimum acknowledged size. This is the most that can be
- * removed from the buffer.
+ * Work out the minimum used size. This is the most that can be removed
+ * from the buffer.
*/
- minimum = wp->offset.acknowledged;
- if (wp->pipe_fd != -1 && wp->pipe_offset.acknowledged < minimum)
- minimum = wp->pipe_offset.acknowledged;
+ minimum = wp->offset.used;
+ if (wp->pipe_fd != -1 && wp->pipe_offset.used < minimum)
+ minimum = wp->pipe_offset.used;
TAILQ_FOREACH(c, &clients, entry) {
if (c->session == NULL)
continue;
@@ -1530,11 +1535,13 @@ server_client_check_pane_buffer(struct window_pane *wp)
if (!flag)
off = 0;
- log_debug("%s: %s has %zu bytes used, %zu bytes acknowledged "
- "for %%%u", __func__, c->name, wpo->used, wpo->acknowledged,
- wp->id);
- if (wpo->acknowledged < minimum)
- minimum = wpo->acknowledged;
+ log_debug("%s: %s has %zu bytes used for %%%u", __func__,
+ c->name, wpo->used - wp->base_offset, wp->id);
+ if (wpo->used - wp->base_offset > SERVER_CLIENT_PANE_LIMIT) {
+ control_flush(c);
+ c->flags |= CLIENT_EXIT;
+ } else if (wpo->used < minimum)
+ minimum = wpo->used;
}
if (attached_clients == 0)
off = 0;
@@ -1543,8 +1550,8 @@ server_client_check_pane_buffer(struct window_pane *wp)
goto out;
/* Drain the buffer. */
- log_debug("%s: %%%u has %zu minimum (of %zu) bytes acknowledged",
- __func__, wp->id, minimum, EVBUFFER_LENGTH(evb));
+ log_debug("%s: %%%u has %zu minimum (of %zu) bytes used", __func__,
+ wp->id, minimum, EVBUFFER_LENGTH(evb));
evbuffer_drain(evb, minimum);
/*
@@ -1553,20 +1560,15 @@ server_client_check_pane_buffer(struct window_pane *wp)
*/
if (wp->base_offset > SIZE_MAX - minimum) {
log_debug("%s: %%%u base offset has wrapped", __func__, wp->id);
- wp->offset.acknowledged -= wp->base_offset;
wp->offset.used -= wp->base_offset;
- if (wp->pipe_fd != -1) {
- wp->pipe_offset.acknowledged -= wp->base_offset;
+ if (wp->pipe_fd != -1)
wp->pipe_offset.used -= wp->base_offset;
- }
TAILQ_FOREACH(c, &clients, entry) {
if (c->session == NULL || (~c->flags & CLIENT_CONTROL))
continue;
wpo = control_pane_offset(c, wp, &flag);
- if (wpo != NULL && !flag) {
- wpo->acknowledged -= wp->base_offset;
+ if (wpo != NULL && !flag)
wpo->used -= wp->base_offset;
- }
}
wp->base_offset = minimum;
} else
@@ -1579,6 +1581,7 @@ out:
* clients, all of which are control clients which are not able to
* accept any more data.
*/
+ log_debug("%s: pane %%%u is %s", __func__, wp->id, off ? "off" : "on");
if (off)
bufferevent_disable(wp->event, EV_READ);
else
@@ -1770,12 +1773,16 @@ static void
server_client_check_exit(struct client *c)
{
struct client_file *cf;
+ const char *name = c->exit_session;
- if (~c->flags & CLIENT_EXIT)
- return;
- if (c->flags & CLIENT_EXITED)
+ if ((c->flags & CLIENT_EXITED) || (~c->flags & CLIENT_EXIT))
return;
+ if (c->flags & CLIENT_CONTROL) {
+ control_flush(c);
+ if (!control_all_done(c))
+ return;
+ }
RB_FOREACH(cf, client_files, &c->files) {
if (EVBUFFER_LENGTH(cf->buffer) != 0)
return;
@@ -1783,8 +1790,20 @@ server_client_check_exit(struct client *c)
if (c->flags & CLIENT_ATTACHED)
notify_client("client-detached", c);
- proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval);
c->flags |= CLIENT_EXITED;
+
+ switch (c->exit_type) {
+ case CLIENT_EXIT_RETURN:
+ proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval);
+ break;
+ case CLIENT_EXIT_SHUTDOWN:
+ proc_send(c->peer, MSG_SHUTDOWN, -1, NULL, 0);
+ break;
+ case CLIENT_EXIT_DETACH:
+ proc_send(c->peer, c->exit_msgtype, -1, name, strlen(name) + 1);
+ break;
+ }
+ free(c->exit_session);
}
/* Redraw timer callback. */
@@ -1996,7 +2015,6 @@ server_client_dispatch(struct imsg *imsg, void *arg)
case MSG_EXITING:
if (datalen != 0)
fatalx("bad MSG_EXITING size");
-
c->session = NULL;
tty_close(&c->tty);
proc_send(c->peer, MSG_EXITED, -1, NULL, 0);
@@ -2050,7 +2068,7 @@ server_client_command_done(struct cmdq_item *item, __unused void *data)
if (~c->flags & CLIENT_ATTACHED)
c->flags |= CLIENT_EXIT;
- else if (~c->flags & CLIENT_DETACHING)
+ else if (~c->flags & CLIENT_EXIT)
tty_send_requests(&c->tty);
return (CMD_RETURN_NORMAL);
}
@@ -2372,7 +2390,7 @@ server_client_set_flags(struct client *c, const char *flags)
else
c->flags |= flag;
if (flag == CLIENT_CONTROL_NOOUTPUT)
- control_free_offsets(c);
+ control_reset_offsets(c);
}
free(copy);
}