summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-11-29 15:55:17 +1100
committerDamien Miller <djm@mindrot.org>2000-11-29 15:55:17 +1100
commit43dc8da75cf671fdae296667c1238f223145a528 (patch)
tree48a60a9945b80d2300fc0017b8dad511b7baced0
parent6dbfef63559c7ac29aa7a3fe27a12d814fbd0e83 (diff)
- (djm) Back out all the serverloop.c hacks. sshd will now hang again
if there are background children with open fds.
-rw-r--r--ChangeLog3
-rw-r--r--serverloop.c27
-rw-r--r--session.c3
3 files changed, 7 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index 828478050..5df35b453 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,6 @@
120001129 120001129
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
85static pid_t child_pid; /* Pid of the child. */ 81static pid_t child_pid; /* Pid of the child. */
86static volatile int child_terminated; /* The child has terminated. */ 82static volatile int child_terminated; /* The child has terminated. */
87static volatile int child_has_selected; /* Child has had chance to drain. */
88static volatile int child_wait_status; /* Status from wait(). */ 83static volatile int child_wait_status; /* Status from wait(). */
89 84
90void server_init_dispatch(void); 85void 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);
diff --git a/session.c b/session.c
index b6c847b8f..a0020d426 100644
--- a/session.c
+++ b/session.c
@@ -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