Don't use a bufferevent for the tty, so we can keep better track of what

is being written and when.

Also a manpage typo fix from jmc@.
This commit is contained in:
nicm 2017-02-10 12:59:18 +00:00
parent c6a3446398
commit d22c15107b
4 changed files with 76 additions and 60 deletions

2
tmux.1
View File

@ -860,7 +860,7 @@ If
is given, it specifies a is given, it specifies a
.Ic session group . .Ic session group .
Sessions in the same group share the same set of windows - new windows are Sessions in the same group share the same set of windows - new windows are
linked to all sessions in the grouo and any windows closed removed from all linked to all sessions in the group and any windows closed removed from all
sessions. sessions.
The current and previous window and any session options remain independent and The current and previous window and any session options remain independent and
any session in a group may be killed without affecting the others. any session in a group may be killed without affecting the others.

5
tmux.h
View File

@ -1041,7 +1041,10 @@ struct tty {
u_int rright; u_int rright;
int fd; int fd;
struct bufferevent *event; struct event event_in;
struct evbuffer *in;
struct event event_out;
struct evbuffer *out;
struct termios tio; struct termios tio;

View File

@ -532,8 +532,8 @@ tty_keys_next(struct tty *tty)
key_code key; key_code key;
/* Get key buffer. */ /* Get key buffer. */
buf = EVBUFFER_DATA(tty->event->input); buf = EVBUFFER_DATA(tty->in);
len = EVBUFFER_LENGTH(tty->event->input); len = EVBUFFER_LENGTH(tty->in);
if (len == 0) if (len == 0)
return (0); return (0);
@ -645,7 +645,7 @@ complete_key:
key = (key & KEYC_MASK_MOD) | KEYC_BSPACE; key = (key & KEYC_MASK_MOD) | KEYC_BSPACE;
/* Remove data from buffer. */ /* Remove data from buffer. */
evbuffer_drain(tty->event->input, size); evbuffer_drain(tty->in, size);
/* Remove key timer. */ /* Remove key timer. */
if (event_initialized(&tty->key_timer)) if (event_initialized(&tty->key_timer))
@ -671,7 +671,7 @@ discard_key:
log_debug("discard key %.*s %#llx", (int)size, buf, key); log_debug("discard key %.*s %#llx", (int)size, buf, key);
/* Remove data from buffer. */ /* Remove data from buffer. */
evbuffer_drain(tty->event->input, size); evbuffer_drain(tty->in, size);
return (1); return (1);
} }

121
tty.c
View File

@ -34,11 +34,6 @@
static int tty_log_fd = -1; static int tty_log_fd = -1;
static void tty_init_termios(int, struct termios *, struct bufferevent *);
static void tty_read_callback(struct bufferevent *, void *);
static void tty_error_callback(struct bufferevent *, short, void *);
static int tty_client_ready(struct client *, struct window_pane *); static int tty_client_ready(struct client *, struct window_pane *);
static void tty_set_italics(struct tty *); static void tty_set_italics(struct tty *);
@ -159,6 +154,38 @@ tty_set_size(struct tty *tty, u_int sx, u_int sy)
return (1); return (1);
} }
static void
tty_read_callback(__unused int fd, __unused short events, void *data)
{
struct tty *tty = data;
size_t size = EVBUFFER_LENGTH(tty->in);
int nread;
nread = evbuffer_read(tty->in, tty->fd, -1);
if (nread == -1)
return;
log_debug("%s: read %d bytes (already %zu)", tty->path, nread, size);
while (tty_keys_next(tty))
;
}
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;
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)
event_del(&tty->event_out);
}
int int
tty_open(struct tty *tty, char **cause) tty_open(struct tty *tty, char **cause)
{ {
@ -169,10 +196,14 @@ tty_open(struct tty *tty, char **cause)
} }
tty->flags |= TTY_OPENED; tty->flags |= TTY_OPENED;
tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE|TTY_TIMER); tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE);
tty->event = bufferevent_new(tty->fd, tty_read_callback, NULL, event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ,
tty_error_callback, tty); tty_read_callback, tty);
tty->in = evbuffer_new();
event_set(&tty->event_out, tty->fd, EV_WRITE, tty_write_callback, tty);
tty->out = evbuffer_new();
tty_start_tty(tty); tty_start_tty(tty);
@ -181,50 +212,26 @@ tty_open(struct tty *tty, char **cause)
return (0); return (0);
} }
static void
tty_read_callback(__unused struct bufferevent *bufev, void *data)
{
struct tty *tty = data;
while (tty_keys_next(tty))
;
}
static void
tty_error_callback(__unused struct bufferevent *bufev, __unused short what,
__unused void *data)
{
}
static void
tty_init_termios(int fd, struct termios *orig_tio, struct bufferevent *bufev)
{
struct termios tio;
if (fd == -1 || tcgetattr(fd, orig_tio) != 0)
return;
setblocking(fd, 0);
if (bufev != NULL)
bufferevent_enable(bufev, EV_READ|EV_WRITE);
memcpy(&tio, orig_tio, sizeof tio);
tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP);
tio.c_iflag |= IGNBRK;
tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET);
tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL|
ECHOPRT|ECHOKE|ISIG);
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSANOW, &tio) == 0)
tcflush(fd, TCIOFLUSH);
}
void void
tty_start_tty(struct tty *tty) tty_start_tty(struct tty *tty)
{ {
tty_init_termios(tty->fd, &tty->tio, tty->event); struct termios tio;
if (tty->fd != -1 && tcgetattr(tty->fd, &tty->tio) == 0) {
setblocking(tty->fd, 0);
event_add(&tty->event_in, NULL);
memcpy(&tio, &tty->tio, sizeof tio);
tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP);
tio.c_iflag |= IGNBRK;
tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET);
tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL|
ECHOPRT|ECHOKE|ISIG);
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
if (tcsetattr(tty->fd, TCSANOW, &tio) == 0)
tcflush(tty->fd, TCIOFLUSH);
}
tty_putcode(tty, TTYC_SMCUP); tty_putcode(tty, TTYC_SMCUP);
@ -264,7 +271,8 @@ tty_stop_tty(struct tty *tty)
return; return;
tty->flags &= ~TTY_STARTED; tty->flags &= ~TTY_STARTED;
bufferevent_disable(tty->event, EV_READ|EV_WRITE); event_del(&tty->event_in);
event_del(&tty->event_out);
/* /*
* Be flexible about error handling and try not kill the server just * Be flexible about error handling and try not kill the server just
@ -318,7 +326,10 @@ tty_close(struct tty *tty)
tty_stop_tty(tty); tty_stop_tty(tty);
if (tty->flags & TTY_OPENED) { if (tty->flags & TTY_OPENED) {
bufferevent_free(tty->event); evbuffer_free(tty->in);
event_del(&tty->event_in);
evbuffer_free(tty->out);
event_del(&tty->event_out);
tty_term_free(tty->term); tty_term_free(tty->term);
tty_keys_free(tty); tty_keys_free(tty);
@ -411,11 +422,13 @@ tty_putcode_ptr2(struct tty *tty, enum tty_code_code code, const void *a,
static void static void
tty_add(struct tty *tty, const char *buf, size_t len) tty_add(struct tty *tty, const char *buf, size_t len)
{ {
bufferevent_write(tty->event, buf, len); evbuffer_add(tty->out, buf, len);
log_debug("%s: %.*s", tty->path, (int)len, buf); log_debug("%s: %.*s", tty->path, (int)len, (const char *)buf);
if (tty_log_fd != -1) if (tty_log_fd != -1)
write(tty_log_fd, buf, len); write(tty_log_fd, buf, len);
if (tty->flags & TTY_STARTED)
event_add(&tty->event_out, NULL);
} }
void void
@ -730,7 +743,7 @@ tty_client_ready(struct client *c, struct window_pane *wp)
{ {
if (c->session == NULL || c->tty.term == NULL) if (c->session == NULL || c->tty.term == NULL)
return (0); return (0);
if (c->flags & CLIENT_SUSPENDED) if (c->flags & (CLIENT_REDRAW|CLIENT_SUSPENDED))
return (0); return (0);
if (c->tty.flags & TTY_FREEZE) if (c->tty.flags & TTY_FREEZE)
return (0); return (0);