From 5569ff9723fcacb0e0206f02adbb4b85368bc1bf Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sat, 31 May 2008 20:04:15 +0000 Subject: [PATCH] Don't hang when window closes early; also add lots more debugging. --- CHANGES | 9 ++++++++- NOTES | 9 +++------ TODO | 4 +++- buffer-poll.c | 9 +++++++-- client.c | 28 ++++++++++++++-------------- server.c | 14 +++++++++++--- window.c | 7 ++++--- 7 files changed, 50 insertions(+), 30 deletions(-) diff --git a/CHANGES b/CHANGES index b8e55a0a..6ab95bed 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,10 @@ +31 May 2008 + +* Fix so tmux doesn't hang if the initial window fails for some reason. This + was highlighted by problems on Darwin, thanks to Elias Pipping for the report + and access to a test account. (tmux still won't work on Darwin since its + poll(2) is broken.) + 02 January 2008 * Don't attempt to reset the tty on exit if it has been closed externally. @@ -303,4 +310,4 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.93 2008-05-10 12:50:25 nicm Exp $ +$Id: CHANGES,v 1.94 2008-05-31 20:04:15 nicm Exp $ diff --git a/NOTES b/NOTES index 71cc3abf..aea3a3be 100644 --- a/NOTES +++ b/NOTES @@ -47,7 +47,7 @@ TERM=screen (tmux in screen), xterm, xterm-color and rxvt. Note that tmux (and screen) relies on an AX term capability to detect if the terminal supports "default" (transparent) foreground and background colours. On OpenBSD, TERM=xterm and TERM=xterm-color lack this; TERM=rxvt does have it and works fine -at least with the aterm and (naturally) rxvt terminal emulators. +at least with the aterm and rxvt terminal emulators. For debugging, running tmux with -v or -vv will generate server and client log files in the current directory. @@ -57,9 +57,6 @@ welcome. Please email: nicm@users.sf.net -Or contact me during UK daytime hours (0900 to 2300 UTC or so) as "NicM" on -freenode or efnet IRC. I sometimes ignore private msgs from people I don't -know, so please mention tmux initially (rather than just saying "hi" ;-). - -- Nicholas Marriott -$Id: NOTES,v 1.31 2007-11-26 20:50:31 nicm Exp $ + +$Id: NOTES,v 1.32 2008-05-31 20:04:15 nicm Exp $ diff --git a/TODO b/TODO index 48d4e1cd..e2b461ae 100644 --- a/TODO +++ b/TODO @@ -71,8 +71,10 @@ -- it's not kkeypad/kcursor - fix kkeypad/kcursor - c/p is still borken in some ways +- tobiasu says it is borken on Linux with aterm + TERM=rxvt --- For 0.2 -------------------------------------------------------------------- +-- For 0.3 -------------------------------------------------------------------- - anything which uses cmd_{send,recv}_string will break if the string is split. string length should be part of the command size - chmod +x socket when any client is attached (upd in lost/accept) + diff --git a/buffer-poll.c b/buffer-poll.c index 099ee4ad..5e37bead 100644 --- a/buffer-poll.c +++ b/buffer-poll.c @@ -1,4 +1,4 @@ -/* $Id: buffer-poll.c,v 1.4 2007-11-30 11:08:34 nicm Exp $ */ +/* $Id: buffer-poll.c,v 1.5 2008-05-31 20:04:15 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -41,11 +41,15 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out) { ssize_t n; + log_debug("buffer_poll (%d): fd=%d, revents=%d; out=%zu in=%zu", + getpid(), pfd->fd, pfd->revents, BUFFER_USED(out), BUFFER_USED(in)); + if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP)) return (-1); if (pfd->revents & POLLIN) { buffer_ensure(in, BUFSIZ); n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in)); + log_debug("buffer_poll: fd=%d, read=%zd", pfd->fd, n); if (n == 0) return (-1); if (n == -1) { @@ -55,7 +59,8 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out) buffer_add(in, n); } if (BUFFER_USED(out) > 0 && pfd->revents & POLLOUT) { - n = write(pfd->fd, BUFFER_OUT(out), BUFFER_USED(out)); + n = write(pfd->fd, BUFFER_OUT(out), BUFFER_USED(out)); + log_debug("buffer_poll: fd=%d, write=%zd", pfd->fd, n); if (n == -1) { if (errno != EINTR && errno != EAGAIN) return (-1); diff --git a/client.c b/client.c index 20e5dc33..7acc2eeb 100644 --- a/client.c +++ b/client.c @@ -1,4 +1,4 @@ -/* $Id: client.c,v 1.25 2007-12-06 09:46:21 nicm Exp $ */ +/* $Id: client.c,v 1.26 2008-05-31 20:04:15 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -130,6 +130,19 @@ client_main(struct client_ctx *cctx) if (sigwinch) client_handle_winch(cctx); + switch (client_msg_dispatch(cctx, &error)) { + case -1: + goto out; + case 0: + /* May be more in buffer, don't let poll block. */ + timeout = 0; + break; + default: + /* Out of data, poll may block. */ + timeout = INFTIM; + break; + } + pfd.fd = cctx->srv_fd; pfd.events = POLLIN; if (BUFFER_USED(cctx->srv_out) > 0) @@ -143,19 +156,6 @@ client_main(struct client_ctx *cctx) if (buffer_poll(&pfd, cctx->srv_in, cctx->srv_out) != 0) goto server_dead; - - switch (client_msg_dispatch(cctx, &error)) { - case -1: - goto out; - case 0: - /* May be more in buffer, don't let poll block. */ - timeout = 0; - break; - default: - /* Out of data, poll may block. */ - timeout = INFTIM; - break; - } } out: diff --git a/server.c b/server.c index 89e5970b..dcd115f3 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.44 2007-12-06 09:46:23 nicm Exp $ */ +/* $Id: server.c,v 1.45 2008-05-31 20:04:15 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -153,12 +153,14 @@ server_main(const char *srv_path, int srv_fd) server_fill_clients(&pfd); /* Do the poll. */ - if (poll(pfds, nfds, INFTIM) == -1) { + log_debug("polling %d fds", nfds); + if ((nfds = poll(pfds, nfds, INFTIM)) == -1) { if (errno == EAGAIN || errno == EINTR) continue; fatal("poll failed"); } pfd = pfds; + log_debug("poll returned %d", nfds); /* Handle server socket. */ if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP)) @@ -215,6 +217,7 @@ server_fill_windows(struct pollfd **pfd) (*pfd)->events = POLLIN; if (BUFFER_USED(w->out) > 0) (*pfd)->events |= POLLOUT; + log_debug("adding window %d (%d)", (*pfd)->fd, w->fd); } (*pfd)++; } @@ -229,6 +232,7 @@ server_handle_windows(struct pollfd **pfd) for (i = 0; i < ARRAY_LENGTH(&windows); i++) { if ((w = ARRAY_ITEM(&windows, i)) != NULL) { + log_debug("testing window %d (%d)", (*pfd)->fd, w->fd); if (buffer_poll(*pfd, w->in, w->out) != 0) server_lost_window(w); else @@ -255,16 +259,18 @@ server_fill_clients(struct pollfd **pfd) (*pfd)->events = POLLIN; if (BUFFER_USED(c->out) > 0) (*pfd)->events |= POLLOUT; + log_debug("adding client %d (%d)", (*pfd)->fd, c->fd); } (*pfd)++; - if (c == NULL || c->tty.fd == -1) + if (c == NULL || c->tty.fd == -1 || c->session == NULL) (*pfd)->fd = -1; else { (*pfd)->fd = c->tty.fd; (*pfd)->events = POLLIN; if (BUFFER_USED(c->tty.out) > 0) (*pfd)->events |= POLLOUT; + log_debug("adding tty %d (%d)", (*pfd)->fd, c->tty.fd); } (*pfd)++; } @@ -281,6 +287,7 @@ server_handle_clients(struct pollfd **pfd) c = ARRAY_ITEM(&clients, i); if (c != NULL) { + log_debug("testing client %d (%d)", (*pfd)->fd, c->fd); if (buffer_poll(*pfd, c->in, c->out) != 0) { server_lost_client(c); (*pfd) += 2; @@ -291,6 +298,7 @@ server_handle_clients(struct pollfd **pfd) (*pfd)++; if (c != NULL && c->tty.fd != -1 && c->session != NULL) { + log_debug("testing tty %d (%d)", (*pfd)->fd, c->tty.fd); if (buffer_poll(*pfd, c->tty.in, c->tty.out) != 0) server_lost_client(c); else diff --git a/window.c b/window.c index 61178610..50a2edc1 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.35 2008-01-02 19:22:21 nicm Exp $ */ +/* $Id: window.c,v 1.36 2008-05-31 20:04:15 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -169,7 +169,7 @@ window_create( ws.ws_col = sx; ws.ws_row = sy; - switch (forkpty(&fd, NULL, NULL, &ws)) { + switch (forkpty(&fd, NULL, NULL, &ws)) { case -1: return (NULL); case 0: @@ -178,8 +178,9 @@ window_create( fatal("putenv failed"); } sigreset(); + log_debug("started child: cmd=%s; pid=%d", cmd, getpid()); log_close(); - + execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL); fatal("execl failed"); }