From c9130033a4eb55330e3614fbae9056ab3bf82891 Mon Sep 17 00:00:00 2001 From: mouring Date: Sat, 9 Jun 2001 01:27:31 +0000 Subject: [PATCH] - markus@cvs.openbsd.org 2001/06/04 23:07:21 [clientloop.c serverloop.c sshd.c] set flags in the signal handlers, do real work in the main loop, ok provos@ --- ChangeLog | 4 ++++ clientloop.c | 40 ++++++++++++++++++++------------------ serverloop.c | 55 ++++++++++------------------------------------------ sshd.c | 23 +++++++++++++--------- 4 files changed, 49 insertions(+), 73 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5552ef5c..443c90d1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -39,6 +39,10 @@ [channels.c channels.h session.c] switch uid when cleaning up tmp files and sockets; reported by zen-parse@gmx.net on bugtraq + - markus@cvs.openbsd.org 2001/06/04 23:07:21 + [clientloop.c serverloop.c sshd.c] + set flags in the signal handlers, do real work in the main loop, + ok provos@ 20010606 - OpenBSD CVS Sync diff --git a/clientloop.c b/clientloop.c index 70abee8f..3a1b43dd 100644 --- a/clientloop.c +++ b/clientloop.c @@ -59,7 +59,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.74 2001/05/31 10:30:15 markus Exp $"); +RCSID("$OpenBSD: clientloop.c,v 1.75 2001/06/04 23:07:20 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -102,6 +102,7 @@ extern char *host; * because this is updated in a signal handler. */ static volatile int received_window_change_signal = 0; +static volatile int received_signal = 0; /* Flag indicating whether the user\'s terminal is in non-blocking mode. */ static int in_non_blocking_mode = 0; @@ -171,13 +172,8 @@ window_change_handler(int sig) void signal_handler(int sig) { - if (in_raw_mode()) - leave_raw_mode(); - if (in_non_blocking_mode) - leave_non_blocking(); - channel_stop_listening(); - packet_close(); - fatal("Killed by signal %d.", sig); + received_signal = sig; + quit_pending = 1; } /* @@ -933,14 +929,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /* Stop listening for connections. */ channel_stop_listening(); - /* - * In interactive mode (with pseudo tty) display a message indicating - * that the connection has been closed. - */ - if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { - snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); - buffer_append(&stderr_buffer, buf, strlen(buf)); - } + if (have_pty) + leave_raw_mode(); /* restore blocking io */ if (!isatty(fileno(stdin))) @@ -950,6 +940,21 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) if (!isatty(fileno(stderr))) unset_nonblock(fileno(stderr)); + if (received_signal) { + if (in_non_blocking_mode) /* XXX */ + leave_non_blocking(); + fatal("Killed by signal %d.", received_signal); + } + + /* + * In interactive mode (with pseudo tty) display a message indicating + * that the connection has been closed. + */ + if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { + snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); + buffer_append(&stderr_buffer, buf, strlen(buf)); + } + /* Output any buffered data for stdout. */ while (buffer_len(&stdout_buffer) > 0) { len = write(fileno(stdout), buffer_ptr(&stdout_buffer), @@ -974,9 +979,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) stderr_bytes += len; } - if (have_pty) - leave_raw_mode(); - /* Clear and free any buffers. */ memset(buf, 0, sizeof(buf)); buffer_free(&stdin_buffer); diff --git a/serverloop.c b/serverloop.c index d8026ec5..bafbfb0a 100644 --- a/serverloop.c +++ b/serverloop.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: serverloop.c,v 1.67 2001/05/31 10:30:16 markus Exp $"); +RCSID("$OpenBSD: serverloop.c,v 1.68 2001/06/04 23:07:20 markus Exp $"); #include "xmalloc.h" #include "packet.h" @@ -84,10 +84,7 @@ static u_int buffer_high; /* "Soft" max buffer size. */ * This SIGCHLD kludge is used to detect when the child exits. The server * will exit after that, as soon as forwarded connections have terminated. */ - -static pid_t child_pid; /* Pid of the child. */ static volatile int child_terminated; /* The child has terminated. */ -static volatile int child_wait_status; /* Status from wait(). */ void server_init_dispatch(void); @@ -95,30 +92,11 @@ int client_alive_timeouts = 0; void sigchld_handler(int sig) -{ - int save_errno = errno; - pid_t wait_pid; - - debug("Received SIGCHLD."); - wait_pid = wait((int *) &child_wait_status); - if (wait_pid != -1) { - if (wait_pid != child_pid) - 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)) - child_terminated = 1; - } - signal(SIGCHLD, sigchld_handler); - errno = save_errno; -} -void -sigchld_handler2(int sig) { int save_errno = errno; debug("Received SIGCHLD."); child_terminated = 1; - mysignal(SIGCHLD, sigchld_handler2); + mysignal(SIGCHLD, sigchld_handler); errno = save_errno; } @@ -466,7 +444,6 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) debug("Entering interactive session."); /* Initialize the SIGCHLD kludge. */ - child_pid = pid; child_terminated = 0; signal(SIGCHLD, sigchld_handler); @@ -634,28 +611,16 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) /* Stop listening for channels; this removes unix domain sockets. */ channel_stop_listening(); - /* Wait for the child to exit. Get its exit status. */ - wait_pid = wait(&wait_status); - if (wait_pid == -1) { - /* - * It is possible that the wait was handled by SIGCHLD - * handler. This may result in either: this call - * returning with EINTR, or: this call returning ECHILD. - */ - if (child_terminated) - wait_status = child_wait_status; - else - packet_disconnect("wait: %.100s", strerror(errno)); - } else { - /* Check if it matches the process we forked. */ - if (wait_pid != pid) - error("Strange, wait returned pid %d, expected %d", - wait_pid, pid); - } - /* We no longer want our SIGCHLD handler to be called. */ signal(SIGCHLD, SIG_DFL); + wait_pid = waitpid(-1, &wait_status, child_terminated ? WNOHANG : 0); + if (wait_pid == -1) + packet_disconnect("wait: %.100s", strerror(errno)); + else if (wait_pid != pid) + error("Strange, wait returned pid %d, expected %d", + wait_pid, pid); + /* Check if it exited normally. */ if (WIFEXITED(wait_status)) { /* Yes, normal exit. Get exit status and send it to the client. */ @@ -700,7 +665,7 @@ server_loop2(void) debug("Entering interactive session for SSH2."); - mysignal(SIGCHLD, sigchld_handler2); + mysignal(SIGCHLD, sigchld_handler); child_terminated = 0; connection_in = packet_get_connection_in(); connection_out = packet_get_connection_out(); diff --git a/sshd.c b/sshd.c index 869c1201..1dfcac0d 100644 --- a/sshd.c +++ b/sshd.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.198 2001/05/28 23:58:35 markus Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.199 2001/06/04 23:07:21 markus Exp $"); #include #include @@ -167,8 +167,9 @@ struct { */ int key_do_regen = 0; -/* This is set to true when SIGHUP is received. */ +/* This is set to true when a signal is received. */ int received_sighup = 0; +int received_sigterm = 0; /* session identifier, used by RSA-auth */ u_char session_id[16]; @@ -227,21 +228,16 @@ sighup_restart(void) /* * Generic signal handler for terminating signals in the master daemon. - * These close the listen socket; not closing it seems to cause "Address - * already in use" problems on some machines, which is inconvenient. */ void sigterm_handler(int sig) { - log("Received signal %d; terminating.", sig); - close_listen_socks(); - unlink(options.pid_file); - exit(255); + received_sigterm = sig; } /* * SIGCHLD handler. This is called whenever a child dies. This will then - * reap any zombies left by exited c. + * reap any zombies left by exited children. */ void main_sigchld_handler(int sig) @@ -262,6 +258,8 @@ main_sigchld_handler(int sig) void grace_alarm_handler(int sig) { + /* XXX no idea how fix this signal handler */ + /* Close the connection. */ packet_close(); @@ -939,6 +937,13 @@ main(int ac, char **av) ret = select(maxfd+1, fdset, NULL, NULL, NULL); if (ret < 0 && errno != EINTR) error("select: %.100s", strerror(errno)); + if (received_sigterm) { + log("Received signal %d; terminating.", + received_sigterm); + close_listen_socks(); + unlink(options.pid_file); + exit(255); + } if (key_used && key_do_regen) { generate_ephemeral_server_key(); key_used = 0; -- 2.45.1