]> andersk Git - openssh.git/commitdiff
- (djm) [channels.c serverloop.c] Fix so-called "hang on exit" (bz #52)
authordjm <djm>
Sun, 28 Jan 2007 23:16:28 +0000 (23:16 +0000)
committerdjm <djm>
Sun, 28 Jan 2007 23:16:28 +0000 (23:16 +0000)
   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@

ChangeLog
channels.c
serverloop.c

index cffddac172eaea9d1fee78e3b63e8c43757fe682..8a0523e638b5effd0bfefae221248b3e553ccee4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+20070128
+ - (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@
+
 20070123
  - (dtucker) [openbsd-compat/bsd-snprintf.c] Static declarations for public
    library interfaces aren't very helpful. Fix up the DOPR_OUTCH macro
index 9d522a6c359acd5884b009ecd3dd6e92222ca27a..c68ad6419f854849574baf8f6e1bcaf89b3babf5 100644 (file)
@@ -1449,10 +1449,11 @@ channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset)
        int len;
 
        if (c->rfd != -1 &&
-           FD_ISSET(c->rfd, readset)) {
+           (c->detach_close || FD_ISSET(c->rfd, readset))) {
                errno = 0;
                len = read(c->rfd, buf, sizeof(buf));
-               if (len < 0 && (errno == EINTR || errno == EAGAIN))
+               if (len < 0 && (errno == EINTR ||
+                   (errno == EAGAIN && !(c->isatty && c->detach_close))))
                        return 1;
 #ifndef PTY_ZEROREAD
                if (len <= 0) {
@@ -1604,11 +1605,12 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
                                c->local_consumed += len;
                        }
                } else if (c->extended_usage == CHAN_EXTENDED_READ &&
-                   FD_ISSET(c->efd, readset)) {
+                   (c->detach_close || FD_ISSET(c->efd, readset))) {
                        len = read(c->efd, buf, sizeof(buf));
                        debug2("channel %d: read %d from efd %d",
                            c->self, len, c->efd);
-                       if (len < 0 && (errno == EINTR || errno == EAGAIN))
+                       if (len < 0 && (errno == EINTR ||
+                           (errno == EAGAIN && !c->detach_close)))
                                return 1;
                        if (len <= 0) {
                                debug2("channel %d: closing read-efd %d",
index 69304b5fadaee20ae80d075d6ba82d0dd2270b78..7e373f01bc59c030b41867b8c7e5664d2127e108 100644 (file)
@@ -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) {
This page took 0.244202 seconds and 5 git commands to generate.