summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--TODO16
-rw-r--r--serverloop.c17
3 files changed, 17 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 8c182d6cb..0366d260b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,6 +12,8 @@
12 - Fix rresvport_af failure errors (logic error in bsd-bindresvport.c) 12 - Fix rresvport_af failure errors (logic error in bsd-bindresvport.c)
13 - Fix --with-ipaddr-display option test. Fix from Jarno Huuskonen 13 - Fix --with-ipaddr-display option test. Fix from Jarno Huuskonen
14 <jhuuskon@hytti.uku.fi> 14 <jhuuskon@hytti.uku.fi>
15 - Fix hang on logout if processes are still using the pty. Needs
16 further testing.
15 17
1620000116 1820000116
17 - Renamed --with-xauth-path to --with-xauth 19 - Renamed --with-xauth-path to --with-xauth
diff --git a/TODO b/TODO
index 0eccc9be4..785b49066 100644
--- a/TODO
+++ b/TODO
@@ -8,19 +8,3 @@
8 lack of u_intXX_t types. There must be a better way. 8 lack of u_intXX_t types. There must be a better way.
9 9
10- Move all compatability cruft (bsd-*, fake-*) into subordinate library 10- Move all compatability cruft (bsd-*, fake-*) into subordinate library
11
12- Hanging on logout:
13
14localhost$ ssh remotehost
15remotehost$ sleep 20 &
16remotehost$ logout
17(ssh hangs at logout for 20 seconds)
18
19Worse:
20
21localhost$ ssh root@remotehost
22remotehost# httpd
23remotehost# logout
24(ssh hangs at logout forever)
25
26This appears to be a problem in the server.
diff --git a/serverloop.c b/serverloop.c
index a5ecfe97d..2afca7637 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -36,10 +36,15 @@ static int max_fd; /* Max file descriptor number for select(). */
36/* 36/*
37 * This SIGCHLD kludge is used to detect when the child exits. The server 37 * This SIGCHLD kludge is used to detect when the child exits. The server
38 * will exit after that, as soon as forwarded connections have terminated. 38 * will exit after that, as soon as forwarded connections have terminated.
39 *
40 * After SIGCHLD child_has_selected is set to 1 after the first pass
41 * through the wait_until_can_do_something() select(). This ensures
42 * that the child's output gets a chance to drain before it is yanked.
39 */ 43 */
40 44
41static int child_pid; /* Pid of the child. */ 45static int child_pid; /* Pid of the child. */
42static volatile int child_terminated; /* The child has terminated. */ 46static volatile int child_terminated; /* The child has terminated. */
47static volatile int child_has_selected; /* Child has had chance to drain. */
43static volatile int child_wait_status; /* Status from wait(). */ 48static volatile int child_wait_status; /* Status from wait(). */
44 49
45void 50void
@@ -56,6 +61,7 @@ sigchld_handler(int sig)
56 if (WIFEXITED(child_wait_status) || 61 if (WIFEXITED(child_wait_status) ||
57 WIFSIGNALED(child_wait_status)) 62 WIFSIGNALED(child_wait_status))
58 child_terminated = 1; 63 child_terminated = 1;
64 child_has_selected = 0;
59 } 65 }
60 signal(SIGCHLD, sigchld_handler); 66 signal(SIGCHLD, sigchld_handler);
61 errno = save_errno; 67 errno = save_errno;
@@ -300,6 +306,9 @@ retry_select:
300 else 306 else
301 goto retry_select; 307 goto retry_select;
302 } 308 }
309
310 if (child_terminated)
311 child_has_selected = 1;
303} 312}
304 313
305/* 314/*
@@ -438,6 +447,7 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
438 /* Initialize the SIGCHLD kludge. */ 447 /* Initialize the SIGCHLD kludge. */
439 child_pid = pid; 448 child_pid = pid;
440 child_terminated = 0; 449 child_terminated = 0;
450 child_has_selected = 0;
441 signal(SIGCHLD, sigchld_handler); 451 signal(SIGCHLD, sigchld_handler);
442 452
443 /* Initialize our global variables. */ 453 /* Initialize our global variables. */
@@ -533,8 +543,11 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
533 * descriptors, and we have no more data to send to the 543 * descriptors, and we have no more data to send to the
534 * client, and there is no pending buffered data. 544 * client, and there is no pending buffered data.
535 */ 545 */
536 if (fdout_eof && fderr_eof && !packet_have_data_to_write() && 546 if (((fdout_eof && fderr_eof) ||
537 buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) { 547 (child_terminated && child_has_selected)) &&
548 !packet_have_data_to_write() &&
549 (buffer_len(&stdout_buffer) == 0) &&
550 (buffer_len(&stderr_buffer) == 0)) {
538 if (!channel_still_open()) 551 if (!channel_still_open())
539 goto quit; 552 goto quit;
540 if (!waiting_termination) { 553 if (!waiting_termination) {