From 761bd3c9e3abd835086fad770e32d00642b74591 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Wed, 11 Aug 2010 22:16:04 +0000 Subject: Sync OpenBSD patchset 745: Change the way backoff works. Instead of stopping reading from the pty when the client tty backs up too much, just stop updating the tty and only update the internal screen. Then when the tty recovers, force a redraw. This prevents a dodgy client from causing other clients to go into backoff while still allowing tmux to be responsive (locally) when seeing lots of output. --- server-client.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index 251a0094..d60ee1d8 100644 --- a/server-client.c +++ b/server-client.c @@ -1,4 +1,4 @@ -/* $Id: server-client.c,v 1.38 2010-08-09 21:45:37 tcunha Exp $ */ +/* $Id: server-client.c,v 1.39 2010-08-11 22:16:03 tcunha Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -491,6 +491,50 @@ server_client_check_exit(struct client *c) c->flags &= ~CLIENT_EXIT; } +/* + * Check if the client should backoff. During backoff, data from external + * programs is not written to the terminal. When the existing data drains, the + * client is redrawn. + * + * There are two backoff phases - both the tty and client have backoff flags - + * the first to allow existing data to drain and the latter to ensure backoff + * is disabled until the redraw has finished and prevent the redraw triggering + * another backoff. + */ +void +server_client_check_backoff(struct client *c) +{ + struct tty *tty = &c->tty; + size_t used; + + used = EVBUFFER_LENGTH(tty->event->output); + + /* + * If in the second backoff phase (redrawing), don't check backoff + * until the redraw has completed (or enough of it to drop below the + * backoff threshold). + */ + if (c->flags & CLIENT_BACKOFF) { + if (used > BACKOFF_THRESHOLD) + return; + c->flags &= ~CLIENT_BACKOFF; + return; + } + + /* Once drained, allow data through again and schedule redraw. */ + if (tty->flags & TTY_BACKOFF) { + if (used != 0) + return; + tty->flags &= ~TTY_BACKOFF; + c->flags |= (CLIENT_BACKOFF|CLIENT_REDRAWWINDOW|CLIENT_STATUS); + return; + } + + /* If too much data, start backoff. */ + if (used > BACKOFF_THRESHOLD) + tty->flags |= TTY_BACKOFF; +} + /* Check for client redraws. */ void server_client_check_redraw(struct client *c) @@ -519,6 +563,10 @@ server_client_check_redraw(struct client *c) if (c->flags & CLIENT_REDRAW) { screen_redraw_screen(c, 0, 0); c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS); + } else if (c->flags & CLIENT_REDRAWWINDOW) { + TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) + screen_redraw_pane(c, wp); + c->flags &= ~CLIENT_REDRAWWINDOW; } else { TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) { if (wp->flags & PANE_REDRAW) -- cgit