diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | serverloop.c | 27 | ||||
-rw-r--r-- | session.c | 3 |
3 files changed, 7 insertions, 26 deletions
@@ -1,5 +1,6 @@ | |||
1 | 20001129 | 1 | 20001129 |
2 | - (djm) Fix(?) the ssh hang-on-logout/data-from-child race | 2 | - (djm) Back out all the serverloop.c hacks. sshd will now hang again |
3 | if there are background children with open fds. | ||
3 | - (djm) bsd-rresvport.c bzero -> memset | 4 | - (djm) bsd-rresvport.c bzero -> memset |
4 | - (djm) Don't fail in defines.h on absence of 64 bit types (we will | 5 | - (djm) Don't fail in defines.h on absence of 64 bit types (we will |
5 | still fail during compilation of sftp-server). | 6 | still fail during compilation of sftp-server). |
diff --git a/serverloop.c b/serverloop.c index dfef6f333..d1816b52c 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -76,15 +76,10 @@ static int max_fd; /* Max file descriptor number for select(). */ | |||
76 | /* | 76 | /* |
77 | * This SIGCHLD kludge is used to detect when the child exits. The server | 77 | * This SIGCHLD kludge is used to detect when the child exits. The server |
78 | * will exit after that, as soon as forwarded connections have terminated. | 78 | * will exit after that, as soon as forwarded connections have terminated. |
79 | * | ||
80 | * After SIGCHLD child_has_selected is set to 1 after the first pass | ||
81 | * through the wait_until_can_do_something() select(). This ensures | ||
82 | * that the child's output gets a chance to drain before it is yanked. | ||
83 | */ | 79 | */ |
84 | 80 | ||
85 | static pid_t child_pid; /* Pid of the child. */ | 81 | static pid_t child_pid; /* Pid of the child. */ |
86 | static volatile int child_terminated; /* The child has terminated. */ | 82 | static volatile int child_terminated; /* The child has terminated. */ |
87 | static volatile int child_has_selected; /* Child has had chance to drain. */ | ||
88 | static volatile int child_wait_status; /* Status from wait(). */ | 83 | static volatile int child_wait_status; /* Status from wait(). */ |
89 | 84 | ||
90 | void server_init_dispatch(void); | 85 | void server_init_dispatch(void); |
@@ -102,10 +97,8 @@ sigchld_handler(int sig) | |||
102 | error("Strange, got SIGCHLD and wait returned pid %d but child is %d", | 97 | error("Strange, got SIGCHLD and wait returned pid %d but child is %d", |
103 | wait_pid, child_pid); | 98 | wait_pid, child_pid); |
104 | if (WIFEXITED(child_wait_status) || | 99 | if (WIFEXITED(child_wait_status) || |
105 | WIFSIGNALED(child_wait_status)) { | 100 | WIFSIGNALED(child_wait_status)) |
106 | child_terminated = 1; | 101 | child_terminated = 1; |
107 | child_has_selected = 0; | ||
108 | } | ||
109 | } | 102 | } |
110 | signal(SIGCHLD, sigchld_handler); | 103 | signal(SIGCHLD, sigchld_handler); |
111 | errno = save_errno; | 104 | errno = save_errno; |
@@ -116,7 +109,7 @@ sigchld_handler2(int sig) | |||
116 | int save_errno = errno; | 109 | int save_errno = errno; |
117 | debug("Received SIGCHLD."); | 110 | debug("Received SIGCHLD."); |
118 | child_terminated = 1; | 111 | child_terminated = 1; |
119 | child_has_selected = 0; | 112 | signal(SIGCHLD, sigchld_handler2); |
120 | errno = save_errno; | 113 | errno = save_errno; |
121 | } | 114 | } |
122 | 115 | ||
@@ -268,9 +261,6 @@ retry_select: | |||
268 | else | 261 | else |
269 | goto retry_select; | 262 | goto retry_select; |
270 | } | 263 | } |
271 | |||
272 | if (child_terminated) | ||
273 | child_has_selected = 1; | ||
274 | } | 264 | } |
275 | 265 | ||
276 | /* | 266 | /* |
@@ -422,7 +412,6 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) | |||
422 | /* Initialize the SIGCHLD kludge. */ | 412 | /* Initialize the SIGCHLD kludge. */ |
423 | child_pid = pid; | 413 | child_pid = pid; |
424 | child_terminated = 0; | 414 | child_terminated = 0; |
425 | child_has_selected = 0; | ||
426 | signal(SIGCHLD, sigchld_handler); | 415 | signal(SIGCHLD, sigchld_handler); |
427 | signal(SIGPIPE, SIG_IGN); | 416 | signal(SIGPIPE, SIG_IGN); |
428 | 417 | ||
@@ -528,11 +517,8 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) | |||
528 | * descriptors, and we have no more data to send to the | 517 | * descriptors, and we have no more data to send to the |
529 | * client, and there is no pending buffered data. | 518 | * client, and there is no pending buffered data. |
530 | */ | 519 | */ |
531 | if (((fdout_eof && fderr_eof) || | 520 | if (fdout_eof && fderr_eof && !packet_have_data_to_write() && |
532 | (child_terminated && child_has_selected)) && | 521 | buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) { |
533 | !packet_have_data_to_write() && | ||
534 | (buffer_len(&stdout_buffer) == 0) && | ||
535 | (buffer_len(&stderr_buffer) == 0)) { | ||
536 | if (!channel_still_open()) | 522 | if (!channel_still_open()) |
537 | break; | 523 | break; |
538 | if (!waiting_termination) { | 524 | if (!waiting_termination) { |
@@ -678,13 +664,10 @@ server_loop2(void) | |||
678 | if (packet_not_very_much_data_to_write()) | 664 | if (packet_not_very_much_data_to_write()) |
679 | channel_output_poll(); | 665 | channel_output_poll(); |
680 | wait_until_can_do_something(&readset, &writeset, 0); | 666 | wait_until_can_do_something(&readset, &writeset, 0); |
681 | if (child_terminated && child_has_selected) { | 667 | if (child_terminated) { |
682 | /* XXX: race - assumes only one child has terminated */ | ||
683 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0) | 668 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0) |
684 | session_close_by_pid(pid, status); | 669 | session_close_by_pid(pid, status); |
685 | child_terminated = 0; | 670 | child_terminated = 0; |
686 | child_has_selected = 0; | ||
687 | signal(SIGCHLD, sigchld_handler2); | ||
688 | } | 671 | } |
689 | channel_after_select(&readset, &writeset); | 672 | channel_after_select(&readset, &writeset); |
690 | process_input(&readset); | 673 | process_input(&readset); |
@@ -1901,9 +1901,6 @@ session_exit_message(Session *s, int status) | |||
1901 | */ | 1901 | */ |
1902 | if (c->ostate != CHAN_OUTPUT_CLOSED) | 1902 | if (c->ostate != CHAN_OUTPUT_CLOSED) |
1903 | chan_write_failed(c); | 1903 | chan_write_failed(c); |
1904 | if (c->istate != CHAN_INPUT_CLOSED) | ||
1905 | c->istate = CHAN_INPUT_WAIT_DRAIN; | ||
1906 | |||
1907 | s->chanid = -1; | 1904 | s->chanid = -1; |
1908 | } | 1905 | } |
1909 | 1906 | ||