diff options
author | djm <djm> | 2007-01-28 23:16:28 +0000 |
---|---|---|
committer | djm <djm> | 2007-01-28 23:16:28 +0000 |
commit | 022e51caf14cf252623029120f22c64ba2c1518d (patch) | |
tree | 0a051a7c03a3cebf2369e8731c703ececeac84a7 /serverloop.c | |
parent | 14469cfedd951db41c090d933e1020a65d3b2eb7 (diff) | |
download | openssh-022e51caf14cf252623029120f22c64ba2c1518d.tar.gz |
- (djm) [channels.c serverloop.c] Fix so-called "hang on exit" (bz #52)
when closing a tty session when a background process still holds tty
fds open. Great detective work and patch by Marc Aurele La France,
slightly tweaked by me; ok dtucker@
Diffstat (limited to 'serverloop.c')
-rw-r--r-- | serverloop.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/serverloop.c b/serverloop.c index 69304b5f..7e373f01 100644 --- a/serverloop.c +++ b/serverloop.c @@ -280,6 +280,7 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, struct timeval tv, *tvp; int ret; int client_alive_scheduled = 0; + int program_alive_scheduled = 0; /* * if using client_alive, set the max timeout accordingly, @@ -317,6 +318,7 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, * the client, try to get some more data from the program. */ if (packet_not_very_much_data_to_write()) { + program_alive_scheduled = child_terminated; if (!fdout_eof) FD_SET(fdout, *readsetp); if (!fderr_eof) @@ -362,8 +364,16 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, memset(*writesetp, 0, *nallocp); if (errno != EINTR) error("select: %.100s", strerror(errno)); - } else if (ret == 0 && client_alive_scheduled) - client_alive_check(); + } else { + if (ret == 0 && client_alive_scheduled) + client_alive_check(); + if (!compat20 && program_alive_scheduled && fdin_is_tty) { + if (!fdout_eof) + FD_SET(fdout, *readsetp); + if (!fderr_eof) + FD_SET(fderr, *readsetp); + } + } notify_done(*readsetp); } @@ -407,7 +417,8 @@ process_input(fd_set *readset) if (!fdout_eof && FD_ISSET(fdout, readset)) { errno = 0; len = read(fdout, buf, sizeof(buf)); - if (len < 0 && (errno == EINTR || errno == EAGAIN)) { + if (len < 0 && (errno == EINTR || + (errno == EAGAIN && !child_terminated))) { /* do nothing */ #ifndef PTY_ZEROREAD } else if (len <= 0) { @@ -425,7 +436,8 @@ process_input(fd_set *readset) if (!fderr_eof && FD_ISSET(fderr, readset)) { errno = 0; len = read(fderr, buf, sizeof(buf)); - if (len < 0 && (errno == EINTR || errno == EAGAIN)) { + if (len < 0 && (errno == EINTR || + (errno == EAGAIN && !child_terminated))) { /* do nothing */ #ifndef PTY_ZEROREAD } else if (len <= 0) { |