diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/client.c | 47 | ||||
-rw-r--r-- | usr.bin/tmux/control.c | 59 | ||||
-rw-r--r-- | usr.bin/tmux/server-client.c | 24 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 19 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 3 |
5 files changed, 105 insertions, 47 deletions
diff --git a/usr.bin/tmux/client.c b/usr.bin/tmux/client.c index 0e85944efc9..3c3106194d7 100644 --- a/usr.bin/tmux/client.c +++ b/usr.bin/tmux/client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.146 2020/06/01 09:43:00 nicm Exp $ */ +/* $OpenBSD: client.c,v 1.147 2020/06/10 07:27:10 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -45,11 +45,13 @@ static enum { CLIENT_EXIT_LOST_SERVER, CLIENT_EXIT_EXITED, CLIENT_EXIT_SERVER_EXITED, + CLIENT_EXIT_MESSAGE_PROVIDED } client_exitreason = CLIENT_EXIT_NONE; static int client_exitflag; static int client_exitval; static enum msgtype client_exittype; static const char *client_exitsession; +static char *client_exitmessage; static const char *client_execshell; static const char *client_execcmd; static int client_attached; @@ -207,6 +209,8 @@ client_exit_message(void) return ("exited"); case CLIENT_EXIT_SERVER_EXITED: return ("server exited"); + case CLIENT_EXIT_MESSAGE_PROVIDED: + return (client_exitmessage); } return ("unknown reason"); } @@ -791,13 +795,38 @@ client_dispatch(struct imsg *imsg, __unused void *arg) client_dispatch_wait(imsg); } +/* Process an exit message. */ +static void +client_dispatch_exit_message(char *data, size_t datalen) +{ + int retval; + + if (datalen < sizeof retval && datalen != 0) + fatalx("bad MSG_EXIT size"); + + if (datalen >= sizeof retval) { + memcpy(&retval, data, sizeof retval); + client_exitval = retval; + } + + if (datalen > sizeof retval) { + datalen -= sizeof retval; + data += sizeof retval; + + client_exitmessage = xmalloc(datalen); + memcpy(client_exitmessage, data, datalen); + client_exitmessage[datalen - 1] = '\0'; + + client_exitreason = CLIENT_EXIT_MESSAGE_PROVIDED; + } +} + /* Dispatch imsgs when in wait state (before MSG_READY). */ static void client_dispatch_wait(struct imsg *imsg) { char *data; ssize_t datalen; - int retval; static int pledge_applied; /* @@ -820,12 +849,7 @@ client_dispatch_wait(struct imsg *imsg) switch (imsg->hdr.type) { case MSG_EXIT: case MSG_SHUTDOWN: - if (datalen != sizeof retval && datalen != 0) - fatalx("bad MSG_EXIT size"); - if (datalen == sizeof retval) { - memcpy(&retval, data, sizeof retval); - client_exitval = retval; - } + client_dispatch_exit_message(data, datalen); client_exitflag = 1; client_exit(); break; @@ -916,11 +940,10 @@ client_dispatch_attached(struct imsg *imsg) proc_send(client_peer, MSG_EXITING, -1, NULL, 0); break; case MSG_EXIT: - if (datalen != 0 && datalen != sizeof (int)) - fatalx("bad MSG_EXIT size"); - + client_dispatch_exit_message(data, datalen); + if (client_exitreason == CLIENT_EXIT_NONE) + client_exitreason = CLIENT_EXIT_EXITED; proc_send(client_peer, MSG_EXITING, -1, NULL, 0); - client_exitreason = CLIENT_EXIT_EXITED; break; case MSG_EXITED: if (datalen != 0) diff --git a/usr.bin/tmux/control.c b/usr.bin/tmux/control.c index c404f4b4c67..c944858b293 100644 --- a/usr.bin/tmux/control.c +++ b/usr.bin/tmux/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.39 2020/06/10 06:23:43 nicm Exp $ */ +/* $OpenBSD: control.c,v 1.40 2020/06/10 07:27:10 nicm Exp $ */ /* * Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -89,13 +89,16 @@ struct control_state { struct bufferevent *write_event; }; -/* Low watermark. */ +/* Low and high watermarks. */ #define CONTROL_BUFFER_LOW 512 #define CONTROL_BUFFER_HIGH 8192 /* Minimum to write to each client. */ #define CONTROL_WRITE_MINIMUM 32 +/* Maximum age for clients that are not using pause mode. */ +#define CONTROL_MAXIMUM_AGE 300000 + /* Flags to ignore client. */ #define CONTROL_IGNORE_FLAGS \ (CLIENT_CONTROL_NOOUTPUT| \ @@ -306,6 +309,41 @@ control_write(struct client *c, const char *fmt, ...) va_end(ap); } +/* Check age for this pane. */ +static int +control_check_age(struct client *c, struct window_pane *wp, + struct control_pane *cp) +{ + struct control_block *cb; + uint64_t t, age; + + cb = TAILQ_FIRST(&cp->blocks); + if (cb == NULL) + return (0); + t = get_timer(); + if (cb->t >= t) + return (0); + + age = t - cb->t; + log_debug("%s: %s: %%%u is %llu behind", __func__, c->name, wp->id, + (unsigned long long)age); + + if (c->flags & CLIENT_CONTROL_PAUSEAFTER) { + if (age < c->pause_age) + return (0); + cp->flags |= CONTROL_PANE_PAUSED; + control_discard_pane(c, cp); + control_write(c, "%%pause %%%u", wp->id); + } else { + if (age < CONTROL_MAXIMUM_AGE) + return (0); + c->exit_message = xstrdup("too far behind"); + c->flags |= CLIENT_EXIT; + control_discard(c); + } + return (1); +} + /* Write output from a pane. */ void control_write_output(struct client *c, struct window_pane *wp) @@ -314,7 +352,6 @@ control_write_output(struct client *c, struct window_pane *wp) struct control_pane *cp; struct control_block *cb; size_t new_size; - uint64_t t; if (winlink_find_by_window(&c->session->windows, wp->window) == NULL) return; @@ -328,20 +365,8 @@ control_write_output(struct client *c, struct window_pane *wp) cp = control_add_pane(c, wp); if (cp->flags & (CONTROL_PANE_OFF|CONTROL_PANE_PAUSED)) goto ignore; - if (c->flags & CLIENT_CONTROL_PAUSEAFTER) { - cb = TAILQ_FIRST(&cp->blocks); - if (cb != NULL) { - t = get_timer(); - log_debug("%s: %s: %%%u is %lld behind", __func__, - c->name, wp->id, (long long)t - cb->t); - if (cb->t < t - c->pause_age) { - cp->flags |= CONTROL_PANE_PAUSED; - control_discard_pane(c, cp); - control_write(c, "%%pause %%%u", wp->id); - return; - } - } - } + if (control_check_age(c, wp, cp)) + return; window_pane_get_new_data(wp, &cp->queued, &new_size); if (new_size == 0) diff --git a/usr.bin/tmux/server-client.c b/usr.bin/tmux/server-client.c index dac02cddf5c..44b7632a445 100644 --- a/usr.bin/tmux/server-client.c +++ b/usr.bin/tmux/server-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server-client.c,v 1.356 2020/06/05 11:20:51 nicm Exp $ */ +/* $OpenBSD: server-client.c,v 1.357 2020/06/10 07:27:10 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -57,9 +57,6 @@ 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, @@ -1528,10 +1525,6 @@ server_client_check_pane_buffer(struct window_pane *wp) log_debug("%s: %s has %zu bytes used and %zu left for %%%u", __func__, c->name, wpo->used - wp->base_offset, new_size, wp->id); - if (new_size > SERVER_CLIENT_PANE_LIMIT) { - control_discard(c); - c->flags |= CLIENT_EXIT; - } if (wpo->used < minimum) minimum = wpo->used; } @@ -1766,6 +1759,8 @@ server_client_check_exit(struct client *c) { struct client_file *cf; const char *name = c->exit_session; + char *data; + size_t size, msize; if (c->flags & (CLIENT_DEAD|CLIENT_EXITED)) return; @@ -1788,7 +1783,17 @@ server_client_check_exit(struct client *c) switch (c->exit_type) { case CLIENT_EXIT_RETURN: - proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval); + if (c->exit_message != NULL) { + msize = strlen(c->exit_message) + 1; + size = (sizeof c->retval) + msize; + } else + size = (sizeof c->retval); + data = xmalloc(size); + memcpy(data, &c->retval, sizeof c->retval); + if (c->exit_message != NULL) + memcpy(data + sizeof c->retval, c->exit_message, msize); + proc_send(c->peer, MSG_EXIT, -1, data, size); + free(data); break; case CLIENT_EXIT_SHUTDOWN: proc_send(c->peer, MSG_SHUTDOWN, -1, NULL, 0); @@ -1798,6 +1803,7 @@ server_client_check_exit(struct client *c) break; } free(c->exit_session); + free(c->exit_message); } /* Redraw timer callback. */ diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 4e2105c2b62..2bf63fe7cb1 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.779 2020/06/10 06:23:43 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.780 2020/06/10 07:27:10 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> .\" @@ -5727,29 +5727,32 @@ When a client detaches, it prints a message. This may be one of: .Bl -tag -width Ds -.It [detached (from session ...)] +.It detached (from session ...) The client was detached normally. -.It [detached and SIGHUP] +.It detached and SIGHUP The client was detached and its parent sent the .Dv SIGHUP signal (for example with .Ic detach-client .Fl P ) . -.It [lost tty] +.It lost tty The client's .Xr tty 4 or .Xr pty 4 was unexpectedly destroyed. -.It [terminated] +.It terminated The client was killed with .Dv SIGTERM . -.It [exited] +.It too far behind +The client is in control mode and became unable to keep up with the data from +.Nm . +.It exited The server exited when it had no sessions. -.It [server exited] +.It server exited The server exited when it received .Dv SIGTERM . -.It [server exited unexpectedly] +.It server exited unexpectedly The server crashed or otherwise exited without telling the client the reason. .El .Sh TERMINFO EXTENSIONS diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index b8131ad7193..60866213b6d 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1065 2020/06/05 11:20:51 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1066 2020/06/10 07:27:10 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -1668,6 +1668,7 @@ struct client { } exit_type; enum msgtype exit_msgtype; char *exit_session; + char *exit_message; struct key_table *keytable; |