diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2001-10-09 21:59:42 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2001-10-09 21:59:42 +0000 |
commit | 8cdd0aef6434e6e026b5a375168eeaf1b14919d2 (patch) | |
tree | 9889cd3c19b5a4e134070291aa2024259334c406 /usr.bin | |
parent | 1bed9aad8b2cb1ea27af58b1807d78637109a17b (diff) |
simplify session close: no more delayed session_close, no more blocking wait() calls.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/ssh/channels.c | 18 | ||||
-rw-r--r-- | usr.bin/ssh/channels.h | 4 | ||||
-rw-r--r-- | usr.bin/ssh/serverloop.c | 38 | ||||
-rw-r--r-- | usr.bin/ssh/session.c | 44 | ||||
-rw-r--r-- | usr.bin/ssh/session.h | 4 |
5 files changed, 40 insertions, 68 deletions
diff --git a/usr.bin/ssh/channels.c b/usr.bin/ssh/channels.c index fb69849a960..4f7f33b685d 100644 --- a/usr.bin/ssh/channels.c +++ b/usr.bin/ssh/channels.c @@ -39,7 +39,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.138 2001/10/08 11:48:57 markus Exp $"); +RCSID("$OpenBSD: channels.c,v 1.139 2001/10/09 21:59:41 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -359,22 +359,6 @@ channel_free_all(void) channel_free(channels[i]); } -void -channel_detach_all(void) -{ - int i; - Channel *c; - - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c != NULL && c->detach_user != NULL) { - debug("channel_detach_all: channel %d", c->self); - c->detach_user(c->self, NULL); - c->detach_user = NULL; - } - } -} - /* * Closes the sockets/fds of all channels. This is used to close extra file * descriptors after a fork. diff --git a/usr.bin/ssh/channels.h b/usr.bin/ssh/channels.h index 49a9df9dd7d..090d2ca6e64 100644 --- a/usr.bin/ssh/channels.h +++ b/usr.bin/ssh/channels.h @@ -32,7 +32,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$OpenBSD: channels.h,v 1.48 2001/10/07 17:49:40 markus Exp $"); */ +/* RCSID("$OpenBSD: channels.h,v 1.49 2001/10/09 21:59:41 markus Exp $"); */ #ifndef CHANNEL_H #define CHANNEL_H @@ -143,7 +143,6 @@ Channel *channel_new(char *, int, int, int, int, int, int, int, char *, int); void channel_set_fds(int, int, int, int, int, int); void channel_free(Channel *); void channel_free_all(void); -void channel_detach_all(void); void channel_stop_listening(void); void channel_send_open(int); @@ -177,7 +176,6 @@ void channel_output_poll(void); int channel_not_very_much_buffered_data(void); void channel_close_all(void); -void channel_free_all(void); int channel_still_open(void); char *channel_open_message(void); int channel_find_open(void); diff --git a/usr.bin/ssh/serverloop.c b/usr.bin/ssh/serverloop.c index 2460b0b2744..94886dbadd1 100644 --- a/usr.bin/ssh/serverloop.c +++ b/usr.bin/ssh/serverloop.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: serverloop.c,v 1.80 2001/10/09 19:51:18 markus Exp $"); +RCSID("$OpenBSD: serverloop.c,v 1.81 2001/10/09 21:59:41 markus Exp $"); #include "xmalloc.h" #include "packet.h" @@ -674,6 +674,7 @@ server_loop2(Authctxt *authctxt) fd_set *readset = NULL, *writeset = NULL; int rekeying = 0, max_fd, status, nalloc = 0; pid_t pid; + sigset_t oset, nset; debug("Entering interactive session for SSH2."); @@ -696,12 +697,17 @@ server_loop2(Authctxt *authctxt) channel_output_poll(); wait_until_can_do_something(&readset, &writeset, &max_fd, &nalloc, 0); + + /* block SIGCHLD while we check for dead children */ + sigemptyset(&nset); + sigaddset(&nset, SIGCHLD); + sigprocmask(SIG_BLOCK, &nset, &oset); if (child_terminated) { while ((pid = waitpid(-1, &status, WNOHANG)) > 0) session_close_by_pid(pid, status); - /* XXX race */ child_terminated = 0; } + sigprocmask(SIG_SETMASK, &oset, NULL); if (!rekeying) channel_after_select(readset, writeset); process_input(readset); @@ -709,35 +715,21 @@ server_loop2(Authctxt *authctxt) break; process_output(writeset); } - /* close all channels, no more reads and writes */ - channel_close_all(); - if (readset) xfree(readset); if (writeset) xfree(writeset); - signal(SIGCHLD, SIG_DFL); + /* free all channels, no more reads and writes */ + channel_free_all(); - /* collect dead children */ + /* collect remaining dead children, XXX not necessary? */ + signal(SIGCHLD, SIG_DFL); while ((pid = waitpid(-1, &status, WNOHANG)) > 0) session_close_by_pid(pid, status); - /* - * there is a race between channel_detach_all() killing remaining - * children and children dying before kill() - */ - channel_detach_all(); - - while (session_have_children()) { - pid = waitpid(-1, &status, 0); - if (pid > 0) - session_close_by_pid(pid, status); - else { - error("waitpid returned %d: %s", pid, strerror(errno)); - break; - } - } - channel_free_all(); + + /* close remaining sessions, e.g remove wtmp entries */ + session_close_all(); } static void diff --git a/usr.bin/ssh/session.c b/usr.bin/ssh/session.c index 8ff8a02cf9d..fa68c391732 100644 --- a/usr.bin/ssh/session.c +++ b/usr.bin/ssh/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.105 2001/10/09 19:32:49 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.106 2001/10/09 21:59:41 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -1567,22 +1567,6 @@ session_close_by_pid(pid_t pid, int status) session_close(s); } -int -session_have_children(void) -{ - int i; - - for(i = 0; i < MAX_SESSIONS; i++) { - Session *s = &sessions[i]; - if (s->used && s->pid != -1) { - debug("session_have_children: id %d pid %d", i, s->pid); - return 1; - } - } - debug("session_have_children: no more children"); - return 0; -} - /* * this is called when a channel dies before * the session 'child' itself dies @@ -1600,15 +1584,29 @@ session_close_by_channel(int id, void *arg) s->chanid = -1; debug("session_close_by_channel: channel %d kill %d", id, s->pid); - if (s->pid == 0) { - /* close session immediately */ - session_close(s); - } else { - /* notify child, delay session cleanup */ - if (kill(s->pid, (s->ttyfd == -1) ? SIGTERM : SIGHUP) < 0) + if (s->pid != 0) { + /* notify child */ + if (kill(s->pid, SIGHUP) < 0) error("session_close_by_channel: kill %d: %s", s->pid, strerror(errno)); } + session_close(s); +} + +void +session_close_all(void) +{ + int i; + for(i = 0; i < MAX_SESSIONS; i++) { + Session *s = &sessions[i]; + if (s->used) { + if (s->chanid != -1) { + channel_cancel_cleanup(s->chanid); + s->chanid = -1; + } + session_close(s); + } + } } static char * diff --git a/usr.bin/ssh/session.h b/usr.bin/ssh/session.h index a04fa6f2bcc..d2b0d936409 100644 --- a/usr.bin/ssh/session.h +++ b/usr.bin/ssh/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.11 2001/07/02 13:59:15 markus Exp $ */ +/* $OpenBSD: session.h,v 1.12 2001/10/09 21:59:41 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -32,6 +32,6 @@ int session_open(Authctxt*, int); void session_input_channel_req(int, void *); void session_close_by_pid(pid_t, int); void session_close_by_channel(int, void *); -int session_have_children(void); +void session_close_all(void); #endif |