mirror of
https://github.com/tmux/tmux.git
synced 2025-01-05 23:38:48 +00:00
Push stdout and stderr to clients more aggressively, and add an event to
continue if the send fails.
This commit is contained in:
parent
908e6bb68f
commit
c56b81a2ce
4
client.c
4
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().
|
* "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");
|
fatal("pledge failed");
|
||||||
|
|
||||||
/* Free stuff that is not used in the client. */
|
/* 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.
|
* get the first message from the server.
|
||||||
*/
|
*/
|
||||||
if (!pledge_applied) {
|
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");
|
fatal("pledge failed");
|
||||||
pledge_applied = 1;
|
pledge_applied = 1;
|
||||||
};
|
};
|
||||||
|
@ -203,7 +203,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
free(buf);
|
free(buf);
|
||||||
if (args_has(args, 'P') && len > 0)
|
if (args_has(args, 'P') && len > 0)
|
||||||
evbuffer_add(c->stdout_data, "\n", 1);
|
evbuffer_add(c->stdout_data, "\n", 1);
|
||||||
server_push_stdout(c);
|
server_client_push_stdout(c);
|
||||||
} else {
|
} else {
|
||||||
bufname = NULL;
|
bufname = NULL;
|
||||||
if (args_has(args, 'b'))
|
if (args_has(args, 'b'))
|
||||||
|
@ -160,7 +160,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
|
|||||||
free(saved);
|
free(saved);
|
||||||
}
|
}
|
||||||
evbuffer_add_printf(c->stderr_data, "%s", cause);
|
evbuffer_add_printf(c->stderr_data, "%s", cause);
|
||||||
server_push_stderr(c);
|
server_client_push_stderr(c);
|
||||||
free(pdata);
|
free(pdata);
|
||||||
free(cause);
|
free(cause);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
|
|||||||
} else
|
} else
|
||||||
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
|
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
|
||||||
evbuffer_add(c->stdout_data, "\n", 1);
|
evbuffer_add(c->stdout_data, "\n", 1);
|
||||||
server_push_stdout(c);
|
server_client_push_stdout(c);
|
||||||
} else {
|
} else {
|
||||||
w = c->session->curw->window;
|
w = c->session->curw->window;
|
||||||
if (w->active->mode != &window_copy_mode) {
|
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, msg, msglen);
|
||||||
evbuffer_add(c->stderr_data, "\n", 1);
|
evbuffer_add(c->stderr_data, "\n", 1);
|
||||||
server_push_stderr(c);
|
server_client_push_stderr(c);
|
||||||
c->retval = 1;
|
c->retval = 1;
|
||||||
} else {
|
} else {
|
||||||
*msg = toupper((u_char) *msg);
|
*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,
|
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
|
||||||
(long) cmdq->time, cmdq->number, flags);
|
(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. */
|
/* Add command list to queue and begin processing if needed. */
|
||||||
|
@ -130,7 +130,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
|
|
||||||
do_stdout:
|
do_stdout:
|
||||||
evbuffer_add(c->stdout_data, bufdata, bufsize);
|
evbuffer_add(c->stdout_data, bufdata, bufsize);
|
||||||
server_push_stdout(c);
|
server_client_push_stdout(c);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
do_print:
|
do_print:
|
||||||
|
@ -37,7 +37,7 @@ control_write(struct client *c, const char *fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
evbuffer_add(c->stdout_data, "\n", 1);
|
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. */
|
/* 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_buffer(c->stdout_data, buffer);
|
||||||
evbuffer_add(c->stdout_data, "\n", 1);
|
evbuffer_add(c->stdout_data, "\n", 1);
|
||||||
server_push_stdout(c);
|
server_client_push_stdout(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Control input callback. Read lines and fire commands. */
|
/* Control input callback. Read lines and fire commands. */
|
||||||
|
@ -1035,9 +1035,6 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
|||||||
server_client_dispatch_shell(c);
|
server_client_dispatch_shell(c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
server_push_stdout(c);
|
|
||||||
server_push_stderr(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle command message. */
|
/* Handle command message. */
|
||||||
@ -1214,3 +1211,90 @@ server_client_dispatch_shell(struct client *c)
|
|||||||
|
|
||||||
proc_kill_peer(c->peer);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
44
server-fn.c
44
server-fn.c
@ -450,50 +450,6 @@ server_callback_identify(unused int fd, unused short events, void *data)
|
|||||||
server_clear_identify(c);
|
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. */
|
/* Set stdin callback. */
|
||||||
int
|
int
|
||||||
server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int,
|
server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int,
|
||||||
|
2
server.c
2
server.c
@ -175,7 +175,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
|
|||||||
|
|
||||||
if (debug_level > 3)
|
if (debug_level > 3)
|
||||||
tty_create_log();
|
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)
|
"ps", NULL) != 0)
|
||||||
fatal("pledge failed");
|
fatal("pledge failed");
|
||||||
|
|
||||||
|
2
tmux.c
2
tmux.c
@ -255,7 +255,7 @@ main(int argc, char **argv)
|
|||||||
if (shell_cmd != NULL && argc != 0)
|
if (shell_cmd != NULL && argc != 0)
|
||||||
usage();
|
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)
|
"proc exec tty ps", NULL) != 0)
|
||||||
err(1, "pledge");
|
err(1, "pledge");
|
||||||
|
|
||||||
|
4
tmux.h
4
tmux.h
@ -1781,6 +1781,8 @@ int server_client_open(struct client *, char **);
|
|||||||
void server_client_unref(struct client *);
|
void server_client_unref(struct client *);
|
||||||
void server_client_lost(struct client *);
|
void server_client_lost(struct client *);
|
||||||
void server_client_loop(void);
|
void server_client_loop(void);
|
||||||
|
void server_client_push_stdout(struct client *);
|
||||||
|
void server_client_push_stderr(struct client *);
|
||||||
|
|
||||||
/* server-fn.c */
|
/* server-fn.c */
|
||||||
void server_fill_environ(struct session *, struct environ *);
|
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_check_unattached(void);
|
||||||
void server_set_identify(struct client *);
|
void server_set_identify(struct client *);
|
||||||
void server_clear_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 server_set_stdin_callback(struct client *, void (*)(struct client *,
|
||||||
int, void *), void *, char **);
|
int, void *), void *, char **);
|
||||||
void server_unzoom_window(struct window *);
|
void server_unzoom_window(struct window *);
|
||||||
|
Loading…
Reference in New Issue
Block a user