summaryrefslogtreecommitdiff
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
parent07877ca68066593473fbe29dd309dcdc61b6d629 (diff)
- (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@
-rw-r--r--ChangeLog8
-rw-r--r--channels.c10
-rw-r--r--serverloop.c20
3 files changed, 29 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 7dd2e4ab8..481bcfddf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
120070128
2 - (djm) [channels.c serverloop.c] Fix so-called "hang on exit" (bz #52)
3 when closing a tty session when a background process still holds tty
4 fds open. Great detective work and patch by Marc Aurele La France,
5 slightly tweaked by me; ok dtucker@
6
120070123 720070123
2 - (dtucker) [openbsd-compat/bsd-snprintf.c] Static declarations for public 8 - (dtucker) [openbsd-compat/bsd-snprintf.c] Static declarations for public
3 library interfaces aren't very helpful. Fix up the DOPR_OUTCH macro 9 library interfaces aren't very helpful. Fix up the DOPR_OUTCH macro
@@ -2686,4 +2692,4 @@
2686 OpenServer 6 and add osr5bigcrypt support so when someone migrates 2692 OpenServer 6 and add osr5bigcrypt support so when someone migrates
2687 passwords between UnixWare and OpenServer they will still work. OK dtucker@ 2693 passwords between UnixWare and OpenServer they will still work. OK dtucker@
2688 2694
2689$Id: ChangeLog,v 1.4608 2007/01/23 13:07:29 dtucker Exp $ 2695$Id: ChangeLog,v 1.4609 2007/01/28 23:16:28 djm Exp $
diff --git a/channels.c b/channels.c
index 9d522a6c3..c68ad6419 100644
--- a/channels.c
+++ b/channels.c
@@ -1449,10 +1449,11 @@ channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset)
1449 int len; 1449 int len;
1450 1450
1451 if (c->rfd != -1 && 1451 if (c->rfd != -1 &&
1452 FD_ISSET(c->rfd, readset)) { 1452 (c->detach_close || FD_ISSET(c->rfd, readset))) {
1453 errno = 0; 1453 errno = 0;
1454 len = read(c->rfd, buf, sizeof(buf)); 1454 len = read(c->rfd, buf, sizeof(buf));
1455 if (len < 0 && (errno == EINTR || errno == EAGAIN)) 1455 if (len < 0 && (errno == EINTR ||
1456 (errno == EAGAIN && !(c->isatty && c->detach_close))))
1456 return 1; 1457 return 1;
1457#ifndef PTY_ZEROREAD 1458#ifndef PTY_ZEROREAD
1458 if (len <= 0) { 1459 if (len <= 0) {
@@ -1604,11 +1605,12 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
1604 c->local_consumed += len; 1605 c->local_consumed += len;
1605 } 1606 }
1606 } else if (c->extended_usage == CHAN_EXTENDED_READ && 1607 } else if (c->extended_usage == CHAN_EXTENDED_READ &&
1607 FD_ISSET(c->efd, readset)) { 1608 (c->detach_close || FD_ISSET(c->efd, readset))) {
1608 len = read(c->efd, buf, sizeof(buf)); 1609 len = read(c->efd, buf, sizeof(buf));
1609 debug2("channel %d: read %d from efd %d", 1610 debug2("channel %d: read %d from efd %d",
1610 c->self, len, c->efd); 1611 c->self, len, c->efd);
1611 if (len < 0 && (errno == EINTR || errno == EAGAIN)) 1612 if (len < 0 && (errno == EINTR ||
1613 (errno == EAGAIN && !c->detach_close)))
1612 return 1; 1614 return 1;
1613 if (len <= 0) { 1615 if (len <= 0) {
1614 debug2("channel %d: closing read-efd %d", 1616 debug2("channel %d: closing read-efd %d",
diff --git a/serverloop.c b/serverloop.c
index 69304b5fa..7e373f01b 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -280,6 +280,7 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
280 struct timeval tv, *tvp; 280 struct timeval tv, *tvp;
281 int ret; 281 int ret;
282 int client_alive_scheduled = 0; 282 int client_alive_scheduled = 0;
283 int program_alive_scheduled = 0;
283 284
284 /* 285 /*
285 * if using client_alive, set the max timeout accordingly, 286 * 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,
317 * the client, try to get some more data from the program. 318 * the client, try to get some more data from the program.
318 */ 319 */
319 if (packet_not_very_much_data_to_write()) { 320 if (packet_not_very_much_data_to_write()) {
321 program_alive_scheduled = child_terminated;
320 if (!fdout_eof) 322 if (!fdout_eof)
321 FD_SET(fdout, *readsetp); 323 FD_SET(fdout, *readsetp);
322 if (!fderr_eof) 324 if (!fderr_eof)
@@ -362,8 +364,16 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
362 memset(*writesetp, 0, *nallocp); 364 memset(*writesetp, 0, *nallocp);
363 if (errno != EINTR) 365 if (errno != EINTR)
364 error("select: %.100s", strerror(errno)); 366 error("select: %.100s", strerror(errno));
365 } else if (ret == 0 && client_alive_scheduled) 367 } else {
366 client_alive_check(); 368 if (ret == 0 && client_alive_scheduled)
369 client_alive_check();
370 if (!compat20 && program_alive_scheduled && fdin_is_tty) {
371 if (!fdout_eof)
372 FD_SET(fdout, *readsetp);
373 if (!fderr_eof)
374 FD_SET(fderr, *readsetp);
375 }
376 }
367 377
368 notify_done(*readsetp); 378 notify_done(*readsetp);
369} 379}
@@ -407,7 +417,8 @@ process_input(fd_set *readset)
407 if (!fdout_eof && FD_ISSET(fdout, readset)) { 417 if (!fdout_eof && FD_ISSET(fdout, readset)) {
408 errno = 0; 418 errno = 0;
409 len = read(fdout, buf, sizeof(buf)); 419 len = read(fdout, buf, sizeof(buf));
410 if (len < 0 && (errno == EINTR || errno == EAGAIN)) { 420 if (len < 0 && (errno == EINTR ||
421 (errno == EAGAIN && !child_terminated))) {
411 /* do nothing */ 422 /* do nothing */
412#ifndef PTY_ZEROREAD 423#ifndef PTY_ZEROREAD
413 } else if (len <= 0) { 424 } else if (len <= 0) {
@@ -425,7 +436,8 @@ process_input(fd_set *readset)
425 if (!fderr_eof && FD_ISSET(fderr, readset)) { 436 if (!fderr_eof && FD_ISSET(fderr, readset)) {
426 errno = 0; 437 errno = 0;
427 len = read(fderr, buf, sizeof(buf)); 438 len = read(fderr, buf, sizeof(buf));
428 if (len < 0 && (errno == EINTR || errno == EAGAIN)) { 439 if (len < 0 && (errno == EINTR ||
440 (errno == EAGAIN && !child_terminated))) {
429 /* do nothing */ 441 /* do nothing */
430#ifndef PTY_ZEROREAD 442#ifndef PTY_ZEROREAD
431 } else if (len <= 0) { 443 } else if (len <= 0) {