From 908e6bb68f127f2bdf0c15ac25dde9ccc06e9104 Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 14 Nov 2015 08:25:12 +0000 Subject: [PATCH 1/2] Log more of UTF-8 input. --- input.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/input.c b/input.c index c56cdc35..babdecdb 100644 --- a/input.c +++ b/input.c @@ -1921,9 +1921,12 @@ input_exit_rename(struct input_ctx *ictx) int input_utf8_open(struct input_ctx *ictx) { - log_debug("%s", __func__); + struct utf8_data *ud = &ictx->utf8data; + + utf8_open(ud, ictx->ch); + + log_debug("%s %hhu", __func__, ud->size); - utf8_open(&ictx->utf8data, ictx->ch); return (0); } @@ -1931,9 +1934,12 @@ input_utf8_open(struct input_ctx *ictx) int input_utf8_add(struct input_ctx *ictx) { + struct utf8_data *ud = &ictx->utf8data; + + utf8_append(ud, ictx->ch); + log_debug("%s", __func__); - utf8_append(&ictx->utf8data, ictx->ch); return (0); } @@ -1941,11 +1947,14 @@ input_utf8_add(struct input_ctx *ictx) int input_utf8_close(struct input_ctx *ictx) { - log_debug("%s", __func__); + struct utf8_data *ud = &ictx->utf8data; - utf8_append(&ictx->utf8data, ictx->ch); + utf8_append(ud, ictx->ch); - utf8_copy(&ictx->cell.cell.data, &ictx->utf8data); + log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size, + (int)ud->size, ud->data, ud->width); + + utf8_copy(&ictx->cell.cell.data, ud); screen_write_cell(&ictx->ctx, &ictx->cell.cell); return (0); From c56b81a2ce815f6d289232f20bb6e07cfd0e36ec Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 14 Nov 2015 09:41:06 +0000 Subject: [PATCH 2/2] Push stdout and stderr to clients more aggressively, and add an event to continue if the send fails. --- client.c | 4 +-- cmd-capture-pane.c | 2 +- cmd-load-buffer.c | 2 +- cmd-queue.c | 6 ++-- cmd-save-buffer.c | 2 +- control.c | 4 +-- server-client.c | 90 ++++++++++++++++++++++++++++++++++++++++++++-- server-fn.c | 44 ----------------------- server.c | 2 +- tmux.c | 2 +- tmux.h | 4 +-- 11 files changed, 101 insertions(+), 61 deletions(-) diff --git a/client.c b/client.c index bc934d33..a6423630 100644 --- a/client.c +++ b/client.c @@ -289,7 +289,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags) * * "sendfd" is dropped later in client_dispatch_wait(). */ - if (pledge("stdio unix sendfd proc exec tty", NULL) != 0) + if (0 && pledge("stdio unix sendfd proc exec tty", NULL) != 0) fatal("pledge failed"); /* Free stuff that is not used in the client. */ @@ -541,7 +541,7 @@ client_dispatch_wait(struct imsg *imsg) * get the first message from the server. */ if (!pledge_applied) { - if (pledge("stdio unix proc exec tty", NULL) != 0) + if (0 && pledge("stdio unix proc exec tty", NULL) != 0) fatal("pledge failed"); pledge_applied = 1; }; diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c index 8958a12d..6a7af47a 100644 --- a/cmd-capture-pane.c +++ b/cmd-capture-pane.c @@ -203,7 +203,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq) free(buf); if (args_has(args, 'P') && len > 0) evbuffer_add(c->stdout_data, "\n", 1); - server_push_stdout(c); + server_client_push_stdout(c); } else { bufname = NULL; if (args_has(args, 'b')) diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c index 40bea9b7..5ac2edc3 100644 --- a/cmd-load-buffer.c +++ b/cmd-load-buffer.c @@ -160,7 +160,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data) free(saved); } evbuffer_add_printf(c->stderr_data, "%s", cause); - server_push_stderr(c); + server_client_push_stderr(c); free(pdata); free(cause); } diff --git a/cmd-queue.c b/cmd-queue.c index 5015981c..2d896212 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -85,7 +85,7 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...) } else evbuffer_add_vprintf(c->stdout_data, fmt, ap); evbuffer_add(c->stdout_data, "\n", 1); - server_push_stdout(c); + server_client_push_stdout(c); } else { w = c->session->curw->window; if (w->active->mode != &window_copy_mode) { @@ -125,7 +125,7 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...) } evbuffer_add(c->stderr_data, msg, msglen); evbuffer_add(c->stderr_data, "\n", 1); - server_push_stderr(c); + server_client_push_stderr(c); c->retval = 1; } else { *msg = toupper((u_char) *msg); @@ -146,7 +146,7 @@ cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags) evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard, (long) cmdq->time, cmdq->number, flags); - server_push_stdout(c); + server_client_push_stdout(c); } /* Add command list to queue and begin processing if needed. */ diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c index 9f3deeda..daef88a8 100644 --- a/cmd-save-buffer.c +++ b/cmd-save-buffer.c @@ -130,7 +130,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq) do_stdout: evbuffer_add(c->stdout_data, bufdata, bufsize); - server_push_stdout(c); + server_client_push_stdout(c); return (CMD_RETURN_NORMAL); do_print: diff --git a/control.c b/control.c index 11fa2d80..f7264944 100644 --- a/control.c +++ b/control.c @@ -37,7 +37,7 @@ control_write(struct client *c, const char *fmt, ...) va_end(ap); evbuffer_add(c->stdout_data, "\n", 1); - server_push_stdout(c); + server_client_push_stdout(c); } /* Write a buffer, adding a terminal newline. Empties buffer. */ @@ -46,7 +46,7 @@ control_write_buffer(struct client *c, struct evbuffer *buffer) { evbuffer_add_buffer(c->stdout_data, buffer); evbuffer_add(c->stdout_data, "\n", 1); - server_push_stdout(c); + server_client_push_stdout(c); } /* Control input callback. Read lines and fire commands. */ diff --git a/server-client.c b/server-client.c index fedc93bd..645492d1 100644 --- a/server-client.c +++ b/server-client.c @@ -1035,9 +1035,6 @@ server_client_dispatch(struct imsg *imsg, void *arg) server_client_dispatch_shell(c); break; } - - server_push_stdout(c); - server_push_stderr(c); } /* Handle command message. */ @@ -1214,3 +1211,90 @@ server_client_dispatch_shell(struct client *c) proc_kill_peer(c->peer); } + +/* Event callback to push more stdout data if any left. */ +static void +server_client_stdout_cb(unused int fd, unused short events, void *arg) +{ + struct client *c = arg; + + if (~c->flags & CLIENT_DEAD) + server_client_push_stdout(c); + server_client_unref(c); +} + +/* Push stdout to client if possible. */ +void +server_client_push_stdout(struct client *c) +{ + struct msg_stdout_data data; + size_t sent, left; + + left = EVBUFFER_LENGTH(c->stdout_data); + while (left != 0) { + sent = left; + if (sent > sizeof data.data) + sent = sizeof data.data; + memcpy(data.data, EVBUFFER_DATA(c->stdout_data), sent); + data.size = sent; + + if (proc_send(c->peer, MSG_STDOUT, -1, &data, sizeof data) != 0) + break; + evbuffer_drain(c->stdout_data, sent); + + left = EVBUFFER_LENGTH(c->stdout_data); + log_debug("%s: client %p, sent %zu, left %zu", __func__, c, + sent, left); + } + if (left != 0) { + c->references++; + event_once(-1, EV_TIMEOUT, server_client_stdout_cb, c, NULL); + log_debug("%s: client %p, queued", __func__, c); + } +} + +/* Event callback to push more stderr data if any left. */ +static void +server_client_stderr_cb(unused int fd, unused short events, void *arg) +{ + struct client *c = arg; + + if (~c->flags & CLIENT_DEAD) + server_client_push_stderr(c); + server_client_unref(c); +} + +/* Push stderr to client if possible. */ +void +server_client_push_stderr(struct client *c) +{ + struct msg_stderr_data data; + size_t sent, left; + + if (c->stderr_data == c->stdout_data) { + server_client_push_stdout(c); + return; + } + + left = EVBUFFER_LENGTH(c->stderr_data); + while (left != 0) { + sent = left; + if (sent > sizeof data.data) + sent = sizeof data.data; + memcpy(data.data, EVBUFFER_DATA(c->stderr_data), sent); + data.size = sent; + + if (proc_send(c->peer, MSG_STDERR, -1, &data, sizeof data) != 0) + break; + evbuffer_drain(c->stderr_data, sent); + + left = EVBUFFER_LENGTH(c->stderr_data); + log_debug("%s: client %p, sent %zu, left %zu", __func__, c, + sent, left); + } + if (left != 0) { + c->references++; + event_once(-1, EV_TIMEOUT, server_client_stderr_cb, c, NULL); + log_debug("%s: client %p, queued", __func__, c); + } +} diff --git a/server-fn.c b/server-fn.c index e9a04cb5..bded7246 100644 --- a/server-fn.c +++ b/server-fn.c @@ -450,50 +450,6 @@ server_callback_identify(unused int fd, unused short events, void *data) server_clear_identify(c); } -/* Push stdout to client if possible. */ -void -server_push_stdout(struct client *c) -{ - struct msg_stdout_data data; - size_t size; - - size = EVBUFFER_LENGTH(c->stdout_data); - if (size == 0) - return; - if (size > sizeof data.data) - size = sizeof data.data; - - memcpy(data.data, EVBUFFER_DATA(c->stdout_data), size); - data.size = size; - - if (proc_send(c->peer, MSG_STDOUT, -1, &data, sizeof data) == 0) - evbuffer_drain(c->stdout_data, size); -} - -/* Push stderr to client if possible. */ -void -server_push_stderr(struct client *c) -{ - struct msg_stderr_data data; - size_t size; - - if (c->stderr_data == c->stdout_data) { - server_push_stdout(c); - return; - } - size = EVBUFFER_LENGTH(c->stderr_data); - if (size == 0) - return; - if (size > sizeof data.data) - size = sizeof data.data; - - memcpy(data.data, EVBUFFER_DATA(c->stderr_data), size); - data.size = size; - - if (proc_send(c->peer, MSG_STDERR, -1, &data, sizeof data) == 0) - evbuffer_drain(c->stderr_data, size); -} - /* Set stdin callback. */ int server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int, diff --git a/server.c b/server.c index 2808c0cc..160b8cac 100644 --- a/server.c +++ b/server.c @@ -175,7 +175,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile) if (debug_level > 3) tty_create_log(); - if (pledge("stdio rpath wpath cpath fattr unix recvfd proc exec tty " + if (0 && pledge("stdio rpath wpath cpath fattr unix recvfd proc exec tty " "ps", NULL) != 0) fatal("pledge failed"); diff --git a/tmux.c b/tmux.c index 5429a7cb..3f110156 100644 --- a/tmux.c +++ b/tmux.c @@ -255,7 +255,7 @@ main(int argc, char **argv) if (shell_cmd != NULL && argc != 0) usage(); - if (pledge("stdio rpath wpath cpath flock fattr unix sendfd recvfd " + if (0 && pledge("stdio rpath wpath cpath flock fattr unix sendfd recvfd " "proc exec tty ps", NULL) != 0) err(1, "pledge"); diff --git a/tmux.h b/tmux.h index 11f5fe58..e69b74b1 100644 --- a/tmux.h +++ b/tmux.h @@ -1781,6 +1781,8 @@ int server_client_open(struct client *, char **); void server_client_unref(struct client *); void server_client_lost(struct client *); void server_client_loop(void); +void server_client_push_stdout(struct client *); +void server_client_push_stderr(struct client *); /* server-fn.c */ void server_fill_environ(struct session *, struct environ *); @@ -1806,8 +1808,6 @@ void server_destroy_session(struct session *); void server_check_unattached(void); void server_set_identify(struct client *); void server_clear_identify(struct client *); -void server_push_stdout(struct client *); -void server_push_stderr(struct client *); int server_set_stdin_callback(struct client *, void (*)(struct client *, int, void *), void *, char **); void server_unzoom_window(struct window *);