summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 82847805..5df35b45 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,6 @@
20001129
- - (djm) Fix(?) the ssh hang-on-logout/data-from-child race
+ - (djm) Back out all the serverloop.c hacks. sshd will now hang again
+ if there are background children with open fds.
- (djm) bsd-rresvport.c bzero -> memset
- (djm) Don't fail in defines.h on absence of 64 bit types (we will
still fail during compilation of sftp-server).
diff --git a/serverloop.c b/serverloop.c
index dfef6f33..d1816b52 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -76,15 +76,10 @@ 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 pid_t 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 server_init_dispatch(void);
@@ -102,10 +97,8 @@ sigchld_handler(int sig)
error("Strange, got SIGCHLD and wait returned pid %d but child is %d",
wait_pid, child_pid);
if (WIFEXITED(child_wait_status) ||
- WIFSIGNALED(child_wait_status)) {
+ WIFSIGNALED(child_wait_status))
child_terminated = 1;
- child_has_selected = 0;
- }
}
signal(SIGCHLD, sigchld_handler);
errno = save_errno;
@@ -116,7 +109,7 @@ sigchld_handler2(int sig)
int save_errno = errno;
debug("Received SIGCHLD.");
child_terminated = 1;
- child_has_selected = 0;
+ signal(SIGCHLD, sigchld_handler2);
errno = save_errno;
}
@@ -268,9 +261,6 @@ retry_select:
else
goto retry_select;
}
-
- if (child_terminated)
- child_has_selected = 1;
}
/*
@@ -422,7 +412,6 @@ server_loop(pid_t 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);
signal(SIGPIPE, SIG_IGN);
@@ -528,11 +517,8 @@ server_loop(pid_t 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) ||
- (child_terminated && child_has_selected)) &&
- !packet_have_data_to_write() &&
- (buffer_len(&stdout_buffer) == 0) &&
- (buffer_len(&stderr_buffer) == 0)) {
+ if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
+ buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) {
if (!channel_still_open())
break;
if (!waiting_termination) {
@@ -678,13 +664,10 @@ server_loop2(void)
if (packet_not_very_much_data_to_write())
channel_output_poll();
wait_until_can_do_something(&readset, &writeset, 0);
- if (child_terminated && child_has_selected) {
- /* XXX: race - assumes only one child has terminated */
+ if (child_terminated) {
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
session_close_by_pid(pid, status);
child_terminated = 0;
- child_has_selected = 0;
- signal(SIGCHLD, sigchld_handler2);
}
channel_after_select(&readset, &writeset);
process_input(&readset);
diff --git a/session.c b/session.c
index b6c847b8..a0020d42 100644
--- a/session.c
+++ b/session.c
@@ -1901,9 +1901,6 @@ session_exit_message(Session *s, int status)
*/
if (c->ostate != CHAN_OUTPUT_CLOSED)
chan_write_failed(c);
- if (c->istate != CHAN_INPUT_CLOSED)
- c->istate = CHAN_INPUT_WAIT_DRAIN;
-
s->chanid = -1;
}