summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2007-01-29 10:16:28 +1100
committerDamien Miller <djm@mindrot.org>2007-01-29 10:16:28 +1100
commite42bd24b22bdce7e58b517d0b797d1d66bbec52b (patch)
treeeade7b9ec5316bd757b75711e9aeaa37b50474ba /serverloop.c
parent07877ca68066593473fbe29dd309dcdc61b6d629 (diff)
downloadopenssh-git-e42bd24b22bdce7e58b517d0b797d1d66bbec52b.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.c20
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) {