From ea8c44d99916c0da1942d03e6ae0e48d998c351b Mon Sep 17 00:00:00 2001 From: dtucker Date: Fri, 23 Jun 2006 11:24:12 +0000 Subject: [PATCH] - (dtucker) [channels.c configure.ac serverloop.c] Bug #1102: Around AIX 4.3.3 ML3 or so, the AIX pty layer starting passing zero-length writes on the pty slave as zero-length reads on the pty master, which sshd interprets as the descriptor closing. Since most things don't do zero length writes this rarely matters, but occasionally it happens, and when it does the SSH pty session appears to hang, so we add a special case for this condition. ok djm@ --- ChangeLog | 7 +++++++ channels.c | 5 +++++ configure.ac | 1 + serverloop.c | 10 ++++++++++ 4 files changed, 23 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9e9946e7..5457f0b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,13 @@ - (dtucker) [README.platform configure.ac openbsd-compat/port-tun.c] Add tunnel support for Mac OS X/Darwin via a third-party tun driver. Patch from reyk@, tested by anil@ + - (dtucker) [channels.c configure.ac serverloop.c] Bug #1102: Around AIX + 4.3.3 ML3 or so, the AIX pty layer starting passing zero-length writes + on the pty slave as zero-length reads on the pty master, which sshd + interprets as the descriptor closing. Since most things don't do zero + length writes this rarely matters, but occasionally it happens, and when + it does the SSH pty session appears to hang, so we add a special case for + this condition. ok djm@ 20060613 - (djm) [getput.h] This file has been replaced by functions in misc.c diff --git a/channels.c b/channels.c index 2fa997ed..239e9dd8 100644 --- a/channels.c +++ b/channels.c @@ -1415,10 +1415,15 @@ channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset) if (c->rfd != -1 && FD_ISSET(c->rfd, readset)) { + errno = 0; len = read(c->rfd, buf, sizeof(buf)); if (len < 0 && (errno == EINTR || errno == EAGAIN)) return 1; +#ifndef PTY_ZEROREAD if (len <= 0) { +#else + if (len < 0 || (len == 0 && errno != 0)) { +#endif debug2("channel %d: read<=0 rfd %d len %d", c->self, c->rfd, len); if (c->type != SSH_CHANNEL_OPEN) { diff --git a/configure.ac b/configure.ac index 19e71a56..70b1fbe4 100644 --- a/configure.ac +++ b/configure.ac @@ -190,6 +190,7 @@ case "$host" in supported by bsd-setproctitle.c]) AC_DEFINE(SSHPAM_CHAUTHTOK_NEEDS_RUID, 1, [AIX 5.2 and 5.3 (and presumably newer) require this]) + AC_DEFINE(PTY_ZEROREAD, 1, [read(1) can return 0 for a non-closed fd]) ;; *-*-cygwin*) check_for_libcrypt_later=1 diff --git a/serverloop.c b/serverloop.c index 021ba68c..c1eb2885 100644 --- a/serverloop.c +++ b/serverloop.c @@ -387,10 +387,15 @@ process_input(fd_set *readset) /* Read and buffer any available stdout data from the program. */ if (!fdout_eof && FD_ISSET(fdout, readset)) { + errno = 0; len = read(fdout, buf, sizeof(buf)); if (len < 0 && (errno == EINTR || errno == EAGAIN)) { /* do nothing */ +#ifdef PTY_ZEROREAD } else if (len <= 0) { +#else + } else if (len < 0 || (len == 0 && errno != 0)) { +#endif fdout_eof = 1; } else { buffer_append(&stdout_buffer, buf, len); @@ -399,10 +404,15 @@ process_input(fd_set *readset) } /* Read and buffer any available stderr data from the program. */ if (!fderr_eof && FD_ISSET(fderr, readset)) { + errno = 0; len = read(fderr, buf, sizeof(buf)); if (len < 0 && (errno == EINTR || errno == EAGAIN)) { /* do nothing */ +#ifdef PTY_ZEROREAD } else if (len <= 0) { +#else + } else if (len < 0 || (len == 0 && errno != 0)) { +#endif fderr_eof = 1; } else { buffer_append(&stderr_buffer, buf, len); -- 2.45.2