]> andersk Git - openssh.git/commitdiff
- (djm) OpenBSD CVS Sync
authordjm <djm>
Fri, 12 Oct 2001 01:35:04 +0000 (01:35 +0000)
committerdjm <djm>
Fri, 12 Oct 2001 01:35:04 +0000 (01:35 +0000)
   - 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 ?

ChangeLog
channels.c
channels.h
clientloop.c
nchan.c
serverloop.c
session.c
session.h

index 5de081ce0d41cfe46556c3c3d6e17ad6810af100..ed9b2bafb909e7f3e7e8ebc7edb3e204e3025a80 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+20011012
+ - (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 ?
+
 20011010
  - (djm) OpenBSD CVS Sync
    - markus@cvs.openbsd.org 2001/10/04 14:34:16
index 04efd7287f7ea5e6aaa82f5711a673893d573cfe..62fd73d74aac2f06423442bac4839a5b382f4c7b 100644 (file)
@@ -39,7 +39,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.139 2001/10/09 21:59:41 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.140 2001/10/10 22:18:47 markus Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -331,10 +331,6 @@ channel_free(Channel *c)
        debug3("channel_free: status: %s", s);
        xfree(s);
 
-       if (c->detach_user != NULL) {
-               debug("channel_free: channel %d: detaching channel user", c->self);
-               c->detach_user(c->self, NULL);
-       }
        if (c->sock != -1)
                shutdown(c->sock, SHUT_RDWR);
        channel_close_fds(c);
@@ -1520,6 +1516,28 @@ channel_handler_init(void)
                channel_handler_init_15();
 }
 
+/* gc dead channels */
+static void
+channel_garbage_collect(Channel *c)
+{
+       if (c == NULL)
+               return;
+       if (c->detach_user != NULL) {
+               if (!chan_is_dead(c, 0))
+                       return;
+               debug("channel %d: gc: notify user", c->self);
+               c->detach_user(c->self, NULL);
+               /* if we still have a callback */
+               if (c->detach_user != NULL)
+                       return;
+               debug("channel %d: gc: user detached", c->self);
+       }
+       if (!chan_is_dead(c, 1))
+               return;
+       debug("channel %d: garbage collecting", c->self);
+       channel_free(c);
+}
+
 static void
 channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
 {
@@ -1537,24 +1555,7 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
                        continue;
                if (ftab[c->type] != NULL)
                        (*ftab[c->type])(c, readset, writeset);
-               if (chan_is_dead(c)) {
-                       /*
-                        * we have to remove the fd's from the select mask
-                        * before the channels are free'd and the fd's are
-                        * closed
-                        */
-                       if (c->wfd != -1)
-                               FD_CLR(c->wfd, writeset);
-                       if (c->rfd != -1)
-                               FD_CLR(c->rfd, readset);
-                       if (c->efd != -1) {
-                               if (c->extended_usage == CHAN_EXTENDED_READ)
-                                       FD_CLR(c->efd, readset);
-                               if (c->extended_usage == CHAN_EXTENDED_WRITE)
-                                       FD_CLR(c->efd, writeset);
-                       }
-                       channel_free(c);
-               }
+               channel_garbage_collect(c);
        }
 }
 
@@ -1625,7 +1626,7 @@ channel_output_poll()
                if (compat20 &&
                    (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {
                        /* XXX is this true? */
-                       debug2("channel %d: no data after CLOSE", c->self);
+                       debug3("channel %d: will not send data after close", c->self);
                        continue;
                }
 
index 090d2ca6e64601cdfa9927ab6d600c8b77d25ee8..89e48009dd59d9087449d1e00b31f8378fb64f75 100644 (file)
@@ -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.49 2001/10/09 21:59:41 markus Exp $"); */
+/* RCSID("$OpenBSD: channels.h,v 1.50 2001/10/10 22:18:47 markus Exp $"); */
 
 #ifndef CHANNEL_H
 #define CHANNEL_H
@@ -214,7 +214,7 @@ void         auth_input_open_request(int, int, void *);
 
 /* channel close */
 
-int     chan_is_dead(Channel *);
+int     chan_is_dead(Channel *, int);
 void    chan_mark_dead(Channel *);
 void    chan_init_iostates(Channel *);
 void    chan_init(void);
index e6da67d51a043d172504176db0627c4d9a191d22..43332d1f4a12929e501aed6e6f50006ad08f2db8 100644 (file)
@@ -59,7 +59,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: clientloop.c,v 1.82 2001/09/17 20:52:47 markus Exp $");
+RCSID("$OpenBSD: clientloop.c,v 1.83 2001/10/10 22:18:47 markus Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -753,6 +753,7 @@ client_channel_closed(int id, void *arg)
        if (id != session_ident)
                error("client_channel_closed: id %d != session_ident %d",
                    id, session_ident);
+       channel_cancel_cleanup(id);
        session_closed = 1;
        if (in_raw_mode())
                leave_raw_mode();
diff --git a/nchan.c b/nchan.c
index 91c34dec89bb68da63a85287e7fe030917cccbeb..2680f0a680bf51a1365cf0c785e73e2b34f38878 100644 (file)
--- a/nchan.c
+++ b/nchan.c
@@ -23,7 +23,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: nchan.c,v 1.31 2001/07/17 21:04:57 markus Exp $");
+RCSID("$OpenBSD: nchan.c,v 1.32 2001/10/10 22:18:47 markus Exp $");
 
 #include "ssh1.h"
 #include "ssh2.h"
@@ -432,7 +432,7 @@ chan_mark_dead(Channel *c)
 }
 
 int
-chan_is_dead(Channel *c)
+chan_is_dead(Channel *c, int send)
 {
        if (c->type == SSH_CHANNEL_ZOMBIE) {
                debug("channel %d: zombie", c->self);
@@ -461,7 +461,16 @@ chan_is_dead(Channel *c)
                       "read": "write");
        } else {
                if (!(c->flags & CHAN_CLOSE_SENT)) {
-                       chan_send_close2(c);
+                       if (send) {
+                               chan_send_close2(c);
+                       } else {
+                               /* channel would be dead if we sent a close */
+                               if (c->flags & CHAN_CLOSE_RCVD) {
+                                       debug("channel %d: almost dead",
+                                           c->self);
+                                       return 1;
+                               }
+                       }
                }
                if ((c->flags & CHAN_CLOSE_SENT) &&
                    (c->flags & CHAN_CLOSE_RCVD)) {
index 8a82af55b7bac6f87ccbaf29754aac4dfd21b886..983fe744389279e23836178181b01861f49abf33 100644 (file)
@@ -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
index 0d6ebdaeafe91f248a6b5f6bcd3cdb8ba1ca1d9c..6ba2e7c77ffc93f184dc9aea2edb85204a6a6653 100644 (file)
--- a/session.c
+++ b/session.c
@@ -33,7 +33,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.106 2001/10/09 21:59:41 markus Exp $");
+RCSID("$OpenBSD: session.c,v 1.107 2001/10/10 22:18:47 markus Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -1958,36 +1958,29 @@ session_close_by_channel(int id, void *arg)
 {
        Session *s = session_by_channel(id);
        if (s == NULL) {
-               debug("session_close_by_channel: no session for channel %d", id);
+               debug("session_close_by_channel: no session for id %d", id);
                return;
        }
-       /* disconnect channel */
-       channel_cancel_cleanup(s->chanid);
-       s->chanid = -1;
-
-       debug("session_close_by_channel: channel %d kill %d", id, s->pid);
+       debug("session_close_by_channel: channel %d child %d", id, s->pid);
        if (s->pid != 0) {
-               /* notify child */
-               if (kill(s->pid, SIGHUP) < 0)
-                       error("session_close_by_channel: kill %d: %s",
-                           s->pid, strerror(errno));
+               /* delay detach */
+               debug("session_close_by_channel: channel %d: has child", id);
+               return;
        }
+       /* detach by removing callback */
+       channel_cancel_cleanup(s->chanid);
+       s->chanid = -1;
        session_close(s);
 }
 
 void
-session_close_all(void)
+session_destroy_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;
-                       }
+               if (s->used) 
                        session_close(s);
-               }
        }
 }
 
index d2b0d9364096094667fcca4e7d48b8772d8771ae..6d5b8e69922dd89bcee8e7c644b77d4c9d1ad90a 100644 (file)
--- a/session.h
+++ b/session.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: session.h,v 1.12 2001/10/09 21:59:41 markus Exp $     */
+/*     $OpenBSD: session.h,v 1.13 2001/10/10 22:18:47 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 *);
-void    session_close_all(void);
+void    session_destroy_all(void);
 
 #endif
This page took 0.904244 seconds and 5 git commands to generate.