diff options
author | Damien Miller <djm@mindrot.org> | 2000-01-17 20:55:18 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2000-01-17 20:55:18 +1100 |
commit | b284b546c092f5f9f8c509c8b49f7d57233a5f3f (patch) | |
tree | a0de7aa63a4aa8716b4eee4fee1fa134c2e6c41c /serverloop.c | |
parent | d426ed6e51b1802e2d47a5ed291232a659dc251a (diff) |
- Fix hang on logout if processes are still using the pty. Needs
further testing.
Diffstat (limited to 'serverloop.c')
-rw-r--r-- | serverloop.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/serverloop.c b/serverloop.c index a5ecfe97..2afca763 100644 --- a/serverloop.c +++ b/serverloop.c @@ -36,10 +36,15 @@ static int max_fd; /* Max file descriptor number for select(). */ /* * This SIGCHLD kludge is used to detect when the child exits. The server * will exit after that, as soon as forwarded connections have terminated. + * + * After SIGCHLD child_has_selected is set to 1 after the first pass + * through the wait_until_can_do_something() select(). This ensures + * that the child's output gets a chance to drain before it is yanked. */ static int child_pid; /* Pid of the child. */ static volatile int child_terminated; /* The child has terminated. */ +static volatile int child_has_selected; /* Child has had chance to drain. */ static volatile int child_wait_status; /* Status from wait(). */ void @@ -56,6 +61,7 @@ sigchld_handler(int sig) if (WIFEXITED(child_wait_status) || WIFSIGNALED(child_wait_status)) child_terminated = 1; + child_has_selected = 0; } signal(SIGCHLD, sigchld_handler); errno = save_errno; @@ -300,6 +306,9 @@ retry_select: else goto retry_select; } + + if (child_terminated) + child_has_selected = 1; } /* @@ -438,6 +447,7 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg) /* Initialize the SIGCHLD kludge. */ child_pid = pid; child_terminated = 0; + child_has_selected = 0; signal(SIGCHLD, sigchld_handler); /* Initialize our global variables. */ @@ -533,8 +543,11 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg) * descriptors, and we have no more data to send to the * client, and there is no pending buffered data. */ - if (fdout_eof && fderr_eof && !packet_have_data_to_write() && - buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) { + if (((fdout_eof && fderr_eof) || + (child_terminated && child_has_selected)) && + !packet_have_data_to_write() && + (buffer_len(&stdout_buffer) == 0) && + (buffer_len(&stderr_buffer) == 0)) { if (!channel_still_open()) goto quit; if (!waiting_termination) { |