diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-02-10 15:38:24 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-02-10 15:38:24 +0000 |
commit | c4c3e09471540a781da8aa4feb4b731474211f90 (patch) | |
tree | c157362948c5e51c59b612877dc6ea4847515c67 /usr.bin | |
parent | a0384b2fa388ade93e18c17dd57162c90fd9c161 (diff) |
Add rather than delete the event if more writing to come.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/tty.c | 63 |
1 files changed, 57 insertions, 6 deletions
diff --git a/usr.bin/tmux/tty.c b/usr.bin/tmux/tty.c index 490cf54d924..cdb5b074fb1 100644 --- a/usr.bin/tmux/tty.c +++ b/usr.bin/tmux/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.244 2017/02/10 12:59:18 nicm Exp $ */ +/* $OpenBSD: tty.c,v 1.245 2017/02/10 15:38:23 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -171,18 +171,59 @@ tty_read_callback(__unused int fd, __unused short events, void *data) } static void +tty_timer_callback(__unused int fd, __unused short events, void *data) +{ + struct tty *tty = data; + struct client *c = tty->client; + const struct timeval tv = { .tv_usec = 250000 }; + + server_client_add_message(c, "%s: %zu discarded", tty->path, + tty->discarded); + + c->flags |= CLIENT_REDRAW; + + if (tty->discarded < 256) { + tty->flags &= ~TTY_BLOCK; + tty_invalidate(tty); + return; + } + tty->discarded = 0; + evtimer_add(&tty->timer, &tv); +} + +static void tty_write_callback(__unused int fd, __unused short events, void *data) { - struct tty *tty = data; - size_t size = EVBUFFER_LENGTH(tty->out); - int nwrite; + struct tty *tty = data; + struct client *c = tty->client; + size_t size = EVBUFFER_LENGTH(tty->out), left; + int nwrite; + const struct timeval tv = { .tv_usec = 250000 }; nwrite = evbuffer_write(tty->out, tty->fd); if (nwrite == -1) return; log_debug("%s: wrote %d bytes (of %zu)", tty->path, nwrite, size); - if (EVBUFFER_LENGTH(tty->out) == 0) + /* + * If we aren't managing to write everything (so we are creating more + * data than the terminal can accept), then the terminal can't keep up. + */ + left = EVBUFFER_LENGTH(tty->out); + if (left > 32768 && nwrite < (int)size && (~tty->flags & TTY_BLOCK)) { + server_client_add_message(c, "%s: can't keep up, %zu discarded", + tty->path, left); + + evbuffer_drain(tty->out, left); + event_del(&tty->event_out); + + tty->discarded = 0; + evtimer_add(&tty->timer, &tv); + + tty->flags |= TTY_BLOCK; + return; + } + if (left == 0) event_del(&tty->event_out); } @@ -196,7 +237,7 @@ tty_open(struct tty *tty, char **cause) } tty->flags |= TTY_OPENED; - tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE); + tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE|TTY_BLOCK|TTY_TIMER); event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ, tty_read_callback, tty); @@ -205,6 +246,8 @@ tty_open(struct tty *tty, char **cause) event_set(&tty->event_out, tty->fd, EV_WRITE, tty_write_callback, tty); tty->out = evbuffer_new(); + evtimer_set(&tty->timer, tty_timer_callback, tty); + tty_start_tty(tty); tty_keys_build(tty); @@ -271,6 +314,9 @@ tty_stop_tty(struct tty *tty) return; tty->flags &= ~TTY_STARTED; + event_del(&tty->timer); + tty->flags &= ~TTY_BLOCK; + event_del(&tty->event_in); event_del(&tty->event_out); @@ -422,6 +468,11 @@ tty_putcode_ptr2(struct tty *tty, enum tty_code_code code, const void *a, static void tty_add(struct tty *tty, const char *buf, size_t len) { + if ((tty->flags & TTY_BLOCK) && (~tty->flags & TTY_FORCE)) { + tty->discarded += len; + return; + } + evbuffer_add(tty->out, buf, len); log_debug("%s: %.*s", tty->path, (int)len, (const char *)buf); |