From acacb718e5452bfdba4810007d5a10eace1a9fec Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 28 Sep 2016 08:30:44 +0000 Subject: [PATCH] Rate limit TIOCSWINSZ on a timer to avoid programs getting hammered with SIGWINCH when the size changes rapidly. To help a problem reported by Rui Pinheiro. --- server-client.c | 40 ++++++++++++++++++++++++++++++++++++---- tmux.h | 2 ++ window.c | 3 +++ 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/server-client.c b/server-client.c index 0c0b2cff..a6ea7bc6 100644 --- a/server-client.c +++ b/server-client.c @@ -765,11 +765,13 @@ server_client_loop(void) } } -/* Check if pane should be resized. */ -void -server_client_check_resize(struct window_pane *wp) +static void +server_client_resize_event(__unused int fd, __unused short events, void *data) { - struct winsize ws; + struct window_pane *wp = data; + struct winsize ws; + + evtimer_del(&wp->resize_timer); if (!(wp->flags & PANE_RESIZE)) return; @@ -784,6 +786,36 @@ server_client_check_resize(struct window_pane *wp) wp->flags &= ~PANE_RESIZE; } +/* Check if pane should be resized. */ +void +server_client_check_resize(struct window_pane *wp) +{ + struct timeval tv = { .tv_usec = 250000 }; + + if (!(wp->flags & PANE_RESIZE)) + return; + + if (!event_initialized(&wp->resize_timer)) + evtimer_set(&wp->resize_timer, server_client_resize_event, wp); + + /* + * The first resize should happen immediately, so if the timer is not + * running, do it now. + */ + if (!evtimer_pending(&wp->resize_timer, NULL)) + server_client_resize_event(-1, 0, wp); + + /* + * If the pane is in the alternate screen, let the timer expire and + * resize to give the application a chance to redraw. If not, keep + * pushing the timer back. + */ + if (wp->saved_grid != NULL && evtimer_pending(&wp->resize_timer, NULL)) + return; + evtimer_del(&wp->resize_timer); + evtimer_add(&wp->resize_timer, &tv); +} + /* Check whether pane should be focused. */ void server_client_check_focus(struct window_pane *wp) diff --git a/tmux.h b/tmux.h index 528b0b7b..46e35aab 100644 --- a/tmux.h +++ b/tmux.h @@ -894,6 +894,8 @@ struct window_pane { int fd; struct bufferevent *event; + struct event resize_timer; + u_int wmark_size; u_int wmark_hits; diff --git a/window.c b/window.c index 33fdd8e7..84b6cc5a 100644 --- a/window.c +++ b/window.c @@ -803,6 +803,9 @@ window_pane_destroy(struct window_pane *wp) close(wp->pipe_fd); } + if (event_initialized(&wp->resize_timer)) + event_del(&wp->resize_timer); + RB_REMOVE(window_pane_tree, &all_window_panes, wp); free((void *)wp->cwd);