diff options
author | djm <djm> | 2001-10-12 01:35:04 +0000 |
---|---|---|
committer | djm <djm> | 2001-10-12 01:35:04 +0000 |
commit | a524f72e0c67aa3f13e81210cb72a116ec250821 (patch) | |
tree | d56cd5de2274eb8610d5accc22a9ff654a9215cd /serverloop.c | |
parent | 359e9c0632b54256fd2bbec39577d224d7209773 (diff) | |
download | openssh-a524f72e0c67aa3f13e81210cb72a116ec250821.tar.gz |
- (djm) OpenBSD CVS Sync
- markus@cvs.openbsd.org 2001/10/10 22:18:47
[channels.c channels.h clientloop.c nchan.c serverloop.c]
[session.c session.h]
try to keep channels open until an exit-status message is sent.
don't kill the login shells if the shells stdin/out/err is closed.
this should now work:
ssh -2n localhost 'exec > /dev/null 2>&1; sleep 10; exit 5'; echo ?
Diffstat (limited to 'serverloop.c')
-rw-r--r-- | serverloop.c | 57 |
1 files changed, 29 insertions, 28 deletions
diff --git a/serverloop.c b/serverloop.c index 8a82af55..983fe744 100644 --- a/serverloop.c +++ b/serverloop.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: serverloop.c,v 1.81 2001/10/09 21:59:41 markus Exp $"); +RCSID("$OpenBSD: serverloop.c,v 1.82 2001/10/10 22:18:47 markus Exp $"); #include "xmalloc.h" #include "packet.h" @@ -208,9 +208,6 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, max_time_milliseconds = options.client_alive_interval * 1000; } - /* When select fails we restart from here. */ -retry_select: - /* Allocate and update select() masks for channel descriptors. */ channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 0); @@ -275,12 +272,11 @@ retry_select: ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); if (ret == -1) { + memset(*readsetp, 0, *maxfdp); + memset(*writesetp, 0, *maxfdp); if (errno != EINTR) error("select: %.100s", strerror(errno)); - else - goto retry_select; - } - if (ret == 0 && client_alive_scheduled) + } else if (ret == 0 && client_alive_scheduled) client_alive_check(); } @@ -668,13 +664,30 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) /* NOTREACHED */ } +static void +collect_children(void) +{ + pid_t pid; + sigset_t oset, nset; + int status; + + /* 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); + child_terminated = 0; + } + sigprocmask(SIG_SETMASK, &oset, NULL); +} + void 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; + int rekeying = 0, max_fd, nalloc = 0; debug("Entering interactive session for SSH2."); @@ -698,16 +711,7 @@ server_loop2(Authctxt *authctxt) 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); - child_terminated = 0; - } - sigprocmask(SIG_SETMASK, &oset, NULL); + collect_children(); if (!rekeying) channel_after_select(readset, writeset); process_input(readset); @@ -715,6 +719,8 @@ server_loop2(Authctxt *authctxt) break; process_output(writeset); } + collect_children(); + if (readset) xfree(readset); if (writeset) @@ -723,13 +729,8 @@ server_loop2(Authctxt *authctxt) /* free all channels, no more reads and writes */ channel_free_all(); - /* collect remaining dead children, XXX not necessary? */ - mysignal(SIGCHLD, SIG_DFL); - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) - session_close_by_pid(pid, status); - - /* close remaining sessions, e.g remove wtmp entries */ - session_close_all(); + /* free remaining sessions, e.g. remove wtmp entries */ + session_destroy_all(); } static void |