diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | channels.c | 49 | ||||
-rw-r--r-- | channels.h | 4 | ||||
-rw-r--r-- | clientloop.c | 3 | ||||
-rw-r--r-- | nchan.c | 15 | ||||
-rw-r--r-- | serverloop.c | 57 | ||||
-rw-r--r-- | session.c | 29 | ||||
-rw-r--r-- | session.h | 4 |
8 files changed, 94 insertions, 79 deletions
@@ -1,3 +1,13 @@ | |||
1 | 20011012 | ||
2 | - (djm) OpenBSD CVS Sync | ||
3 | - markus@cvs.openbsd.org 2001/10/10 22:18:47 | ||
4 | [channels.c channels.h clientloop.c nchan.c serverloop.c] | ||
5 | [session.c session.h] | ||
6 | try to keep channels open until an exit-status message is sent. | ||
7 | don't kill the login shells if the shells stdin/out/err is closed. | ||
8 | this should now work: | ||
9 | ssh -2n localhost 'exec > /dev/null 2>&1; sleep 10; exit 5'; echo ? | ||
10 | |||
1 | 20011010 | 11 | 20011010 |
2 | - (djm) OpenBSD CVS Sync | 12 | - (djm) OpenBSD CVS Sync |
3 | - markus@cvs.openbsd.org 2001/10/04 14:34:16 | 13 | - markus@cvs.openbsd.org 2001/10/04 14:34:16 |
@@ -6695,4 +6705,4 @@ | |||
6695 | - Wrote replacements for strlcpy and mkdtemp | 6705 | - Wrote replacements for strlcpy and mkdtemp |
6696 | - Released 1.0pre1 | 6706 | - Released 1.0pre1 |
6697 | 6707 | ||
6698 | $Id: ChangeLog,v 1.1600 2001/10/10 20:45:43 mouring Exp $ | 6708 | $Id: ChangeLog,v 1.1601 2001/10/12 01:35:04 djm Exp $ |
diff --git a/channels.c b/channels.c index 04efd7287..62fd73d74 100644 --- a/channels.c +++ b/channels.c | |||
@@ -39,7 +39,7 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include "includes.h" | 41 | #include "includes.h" |
42 | RCSID("$OpenBSD: channels.c,v 1.139 2001/10/09 21:59:41 markus Exp $"); | 42 | RCSID("$OpenBSD: channels.c,v 1.140 2001/10/10 22:18:47 markus Exp $"); |
43 | 43 | ||
44 | #include "ssh.h" | 44 | #include "ssh.h" |
45 | #include "ssh1.h" | 45 | #include "ssh1.h" |
@@ -331,10 +331,6 @@ channel_free(Channel *c) | |||
331 | debug3("channel_free: status: %s", s); | 331 | debug3("channel_free: status: %s", s); |
332 | xfree(s); | 332 | xfree(s); |
333 | 333 | ||
334 | if (c->detach_user != NULL) { | ||
335 | debug("channel_free: channel %d: detaching channel user", c->self); | ||
336 | c->detach_user(c->self, NULL); | ||
337 | } | ||
338 | if (c->sock != -1) | 334 | if (c->sock != -1) |
339 | shutdown(c->sock, SHUT_RDWR); | 335 | shutdown(c->sock, SHUT_RDWR); |
340 | channel_close_fds(c); | 336 | channel_close_fds(c); |
@@ -1520,6 +1516,28 @@ channel_handler_init(void) | |||
1520 | channel_handler_init_15(); | 1516 | channel_handler_init_15(); |
1521 | } | 1517 | } |
1522 | 1518 | ||
1519 | /* gc dead channels */ | ||
1520 | static void | ||
1521 | channel_garbage_collect(Channel *c) | ||
1522 | { | ||
1523 | if (c == NULL) | ||
1524 | return; | ||
1525 | if (c->detach_user != NULL) { | ||
1526 | if (!chan_is_dead(c, 0)) | ||
1527 | return; | ||
1528 | debug("channel %d: gc: notify user", c->self); | ||
1529 | c->detach_user(c->self, NULL); | ||
1530 | /* if we still have a callback */ | ||
1531 | if (c->detach_user != NULL) | ||
1532 | return; | ||
1533 | debug("channel %d: gc: user detached", c->self); | ||
1534 | } | ||
1535 | if (!chan_is_dead(c, 1)) | ||
1536 | return; | ||
1537 | debug("channel %d: garbage collecting", c->self); | ||
1538 | channel_free(c); | ||
1539 | } | ||
1540 | |||
1523 | static void | 1541 | static void |
1524 | channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) | 1542 | channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) |
1525 | { | 1543 | { |
@@ -1537,24 +1555,7 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) | |||
1537 | continue; | 1555 | continue; |
1538 | if (ftab[c->type] != NULL) | 1556 | if (ftab[c->type] != NULL) |
1539 | (*ftab[c->type])(c, readset, writeset); | 1557 | (*ftab[c->type])(c, readset, writeset); |
1540 | if (chan_is_dead(c)) { | 1558 | channel_garbage_collect(c); |
1541 | /* | ||
1542 | * we have to remove the fd's from the select mask | ||
1543 | * before the channels are free'd and the fd's are | ||
1544 | * closed | ||
1545 | */ | ||
1546 | if (c->wfd != -1) | ||
1547 | FD_CLR(c->wfd, writeset); | ||
1548 | if (c->rfd != -1) | ||
1549 | FD_CLR(c->rfd, readset); | ||
1550 | if (c->efd != -1) { | ||
1551 | if (c->extended_usage == CHAN_EXTENDED_READ) | ||
1552 | FD_CLR(c->efd, readset); | ||
1553 | if (c->extended_usage == CHAN_EXTENDED_WRITE) | ||
1554 | FD_CLR(c->efd, writeset); | ||
1555 | } | ||
1556 | channel_free(c); | ||
1557 | } | ||
1558 | } | 1559 | } |
1559 | } | 1560 | } |
1560 | 1561 | ||
@@ -1625,7 +1626,7 @@ channel_output_poll() | |||
1625 | if (compat20 && | 1626 | if (compat20 && |
1626 | (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { | 1627 | (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { |
1627 | /* XXX is this true? */ | 1628 | /* XXX is this true? */ |
1628 | debug2("channel %d: no data after CLOSE", c->self); | 1629 | debug3("channel %d: will not send data after close", c->self); |
1629 | continue; | 1630 | continue; |
1630 | } | 1631 | } |
1631 | 1632 | ||
diff --git a/channels.h b/channels.h index 090d2ca6e..89e48009d 100644 --- a/channels.h +++ b/channels.h | |||
@@ -32,7 +32,7 @@ | |||
32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
34 | */ | 34 | */ |
35 | /* RCSID("$OpenBSD: channels.h,v 1.49 2001/10/09 21:59:41 markus Exp $"); */ | 35 | /* RCSID("$OpenBSD: channels.h,v 1.50 2001/10/10 22:18:47 markus Exp $"); */ |
36 | 36 | ||
37 | #ifndef CHANNEL_H | 37 | #ifndef CHANNEL_H |
38 | #define CHANNEL_H | 38 | #define CHANNEL_H |
@@ -214,7 +214,7 @@ void auth_input_open_request(int, int, void *); | |||
214 | 214 | ||
215 | /* channel close */ | 215 | /* channel close */ |
216 | 216 | ||
217 | int chan_is_dead(Channel *); | 217 | int chan_is_dead(Channel *, int); |
218 | void chan_mark_dead(Channel *); | 218 | void chan_mark_dead(Channel *); |
219 | void chan_init_iostates(Channel *); | 219 | void chan_init_iostates(Channel *); |
220 | void chan_init(void); | 220 | void chan_init(void); |
diff --git a/clientloop.c b/clientloop.c index e6da67d51..43332d1f4 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -59,7 +59,7 @@ | |||
59 | */ | 59 | */ |
60 | 60 | ||
61 | #include "includes.h" | 61 | #include "includes.h" |
62 | RCSID("$OpenBSD: clientloop.c,v 1.82 2001/09/17 20:52:47 markus Exp $"); | 62 | RCSID("$OpenBSD: clientloop.c,v 1.83 2001/10/10 22:18:47 markus Exp $"); |
63 | 63 | ||
64 | #include "ssh.h" | 64 | #include "ssh.h" |
65 | #include "ssh1.h" | 65 | #include "ssh1.h" |
@@ -753,6 +753,7 @@ client_channel_closed(int id, void *arg) | |||
753 | if (id != session_ident) | 753 | if (id != session_ident) |
754 | error("client_channel_closed: id %d != session_ident %d", | 754 | error("client_channel_closed: id %d != session_ident %d", |
755 | id, session_ident); | 755 | id, session_ident); |
756 | channel_cancel_cleanup(id); | ||
756 | session_closed = 1; | 757 | session_closed = 1; |
757 | if (in_raw_mode()) | 758 | if (in_raw_mode()) |
758 | leave_raw_mode(); | 759 | leave_raw_mode(); |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: nchan.c,v 1.31 2001/07/17 21:04:57 markus Exp $"); | 26 | RCSID("$OpenBSD: nchan.c,v 1.32 2001/10/10 22:18:47 markus Exp $"); |
27 | 27 | ||
28 | #include "ssh1.h" | 28 | #include "ssh1.h" |
29 | #include "ssh2.h" | 29 | #include "ssh2.h" |
@@ -432,7 +432,7 @@ chan_mark_dead(Channel *c) | |||
432 | } | 432 | } |
433 | 433 | ||
434 | int | 434 | int |
435 | chan_is_dead(Channel *c) | 435 | chan_is_dead(Channel *c, int send) |
436 | { | 436 | { |
437 | if (c->type == SSH_CHANNEL_ZOMBIE) { | 437 | if (c->type == SSH_CHANNEL_ZOMBIE) { |
438 | debug("channel %d: zombie", c->self); | 438 | debug("channel %d: zombie", c->self); |
@@ -461,7 +461,16 @@ chan_is_dead(Channel *c) | |||
461 | "read": "write"); | 461 | "read": "write"); |
462 | } else { | 462 | } else { |
463 | if (!(c->flags & CHAN_CLOSE_SENT)) { | 463 | if (!(c->flags & CHAN_CLOSE_SENT)) { |
464 | chan_send_close2(c); | 464 | if (send) { |
465 | chan_send_close2(c); | ||
466 | } else { | ||
467 | /* channel would be dead if we sent a close */ | ||
468 | if (c->flags & CHAN_CLOSE_RCVD) { | ||
469 | debug("channel %d: almost dead", | ||
470 | c->self); | ||
471 | return 1; | ||
472 | } | ||
473 | } | ||
465 | } | 474 | } |
466 | if ((c->flags & CHAN_CLOSE_SENT) && | 475 | if ((c->flags & CHAN_CLOSE_SENT) && |
467 | (c->flags & CHAN_CLOSE_RCVD)) { | 476 | (c->flags & CHAN_CLOSE_RCVD)) { |
diff --git a/serverloop.c b/serverloop.c index 8a82af55b..983fe7443 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: serverloop.c,v 1.81 2001/10/09 21:59:41 markus Exp $"); | 38 | RCSID("$OpenBSD: serverloop.c,v 1.82 2001/10/10 22:18:47 markus Exp $"); |
39 | 39 | ||
40 | #include "xmalloc.h" | 40 | #include "xmalloc.h" |
41 | #include "packet.h" | 41 | #include "packet.h" |
@@ -208,9 +208,6 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, | |||
208 | max_time_milliseconds = options.client_alive_interval * 1000; | 208 | max_time_milliseconds = options.client_alive_interval * 1000; |
209 | } | 209 | } |
210 | 210 | ||
211 | /* When select fails we restart from here. */ | ||
212 | retry_select: | ||
213 | |||
214 | /* Allocate and update select() masks for channel descriptors. */ | 211 | /* Allocate and update select() masks for channel descriptors. */ |
215 | channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 0); | 212 | channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 0); |
216 | 213 | ||
@@ -275,12 +272,11 @@ retry_select: | |||
275 | ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); | 272 | ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); |
276 | 273 | ||
277 | if (ret == -1) { | 274 | if (ret == -1) { |
275 | memset(*readsetp, 0, *maxfdp); | ||
276 | memset(*writesetp, 0, *maxfdp); | ||
278 | if (errno != EINTR) | 277 | if (errno != EINTR) |
279 | error("select: %.100s", strerror(errno)); | 278 | error("select: %.100s", strerror(errno)); |
280 | else | 279 | } else if (ret == 0 && client_alive_scheduled) |
281 | goto retry_select; | ||
282 | } | ||
283 | if (ret == 0 && client_alive_scheduled) | ||
284 | client_alive_check(); | 280 | client_alive_check(); |
285 | } | 281 | } |
286 | 282 | ||
@@ -668,13 +664,30 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) | |||
668 | /* NOTREACHED */ | 664 | /* NOTREACHED */ |
669 | } | 665 | } |
670 | 666 | ||
667 | static void | ||
668 | collect_children(void) | ||
669 | { | ||
670 | pid_t pid; | ||
671 | sigset_t oset, nset; | ||
672 | int status; | ||
673 | |||
674 | /* block SIGCHLD while we check for dead children */ | ||
675 | sigemptyset(&nset); | ||
676 | sigaddset(&nset, SIGCHLD); | ||
677 | sigprocmask(SIG_BLOCK, &nset, &oset); | ||
678 | if (child_terminated) { | ||
679 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0) | ||
680 | session_close_by_pid(pid, status); | ||
681 | child_terminated = 0; | ||
682 | } | ||
683 | sigprocmask(SIG_SETMASK, &oset, NULL); | ||
684 | } | ||
685 | |||
671 | void | 686 | void |
672 | server_loop2(Authctxt *authctxt) | 687 | server_loop2(Authctxt *authctxt) |
673 | { | 688 | { |
674 | fd_set *readset = NULL, *writeset = NULL; | 689 | fd_set *readset = NULL, *writeset = NULL; |
675 | int rekeying = 0, max_fd, status, nalloc = 0; | 690 | int rekeying = 0, max_fd, nalloc = 0; |
676 | pid_t pid; | ||
677 | sigset_t oset, nset; | ||
678 | 691 | ||
679 | debug("Entering interactive session for SSH2."); | 692 | debug("Entering interactive session for SSH2."); |
680 | 693 | ||
@@ -698,16 +711,7 @@ server_loop2(Authctxt *authctxt) | |||
698 | wait_until_can_do_something(&readset, &writeset, &max_fd, | 711 | wait_until_can_do_something(&readset, &writeset, &max_fd, |
699 | &nalloc, 0); | 712 | &nalloc, 0); |
700 | 713 | ||
701 | /* block SIGCHLD while we check for dead children */ | 714 | collect_children(); |
702 | sigemptyset(&nset); | ||
703 | sigaddset(&nset, SIGCHLD); | ||
704 | sigprocmask(SIG_BLOCK, &nset, &oset); | ||
705 | if (child_terminated) { | ||
706 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0) | ||
707 | session_close_by_pid(pid, status); | ||
708 | child_terminated = 0; | ||
709 | } | ||
710 | sigprocmask(SIG_SETMASK, &oset, NULL); | ||
711 | if (!rekeying) | 715 | if (!rekeying) |
712 | channel_after_select(readset, writeset); | 716 | channel_after_select(readset, writeset); |
713 | process_input(readset); | 717 | process_input(readset); |
@@ -715,6 +719,8 @@ server_loop2(Authctxt *authctxt) | |||
715 | break; | 719 | break; |
716 | process_output(writeset); | 720 | process_output(writeset); |
717 | } | 721 | } |
722 | collect_children(); | ||
723 | |||
718 | if (readset) | 724 | if (readset) |
719 | xfree(readset); | 725 | xfree(readset); |
720 | if (writeset) | 726 | if (writeset) |
@@ -723,13 +729,8 @@ server_loop2(Authctxt *authctxt) | |||
723 | /* free all channels, no more reads and writes */ | 729 | /* free all channels, no more reads and writes */ |
724 | channel_free_all(); | 730 | channel_free_all(); |
725 | 731 | ||
726 | /* collect remaining dead children, XXX not necessary? */ | 732 | /* free remaining sessions, e.g. remove wtmp entries */ |
727 | mysignal(SIGCHLD, SIG_DFL); | 733 | session_destroy_all(); |
728 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0) | ||
729 | session_close_by_pid(pid, status); | ||
730 | |||
731 | /* close remaining sessions, e.g remove wtmp entries */ | ||
732 | session_close_all(); | ||
733 | } | 734 | } |
734 | 735 | ||
735 | static void | 736 | static void |
@@ -33,7 +33,7 @@ | |||
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include "includes.h" | 35 | #include "includes.h" |
36 | RCSID("$OpenBSD: session.c,v 1.106 2001/10/09 21:59:41 markus Exp $"); | 36 | RCSID("$OpenBSD: session.c,v 1.107 2001/10/10 22:18:47 markus Exp $"); |
37 | 37 | ||
38 | #include "ssh.h" | 38 | #include "ssh.h" |
39 | #include "ssh1.h" | 39 | #include "ssh1.h" |
@@ -1958,36 +1958,29 @@ session_close_by_channel(int id, void *arg) | |||
1958 | { | 1958 | { |
1959 | Session *s = session_by_channel(id); | 1959 | Session *s = session_by_channel(id); |
1960 | if (s == NULL) { | 1960 | if (s == NULL) { |
1961 | debug("session_close_by_channel: no session for channel %d", id); | 1961 | debug("session_close_by_channel: no session for id %d", id); |
1962 | return; | 1962 | return; |
1963 | } | 1963 | } |
1964 | /* disconnect channel */ | 1964 | debug("session_close_by_channel: channel %d child %d", id, s->pid); |
1965 | channel_cancel_cleanup(s->chanid); | ||
1966 | s->chanid = -1; | ||
1967 | |||
1968 | debug("session_close_by_channel: channel %d kill %d", id, s->pid); | ||
1969 | if (s->pid != 0) { | 1965 | if (s->pid != 0) { |
1970 | /* notify child */ | 1966 | /* delay detach */ |
1971 | if (kill(s->pid, SIGHUP) < 0) | 1967 | debug("session_close_by_channel: channel %d: has child", id); |
1972 | error("session_close_by_channel: kill %d: %s", | 1968 | return; |
1973 | s->pid, strerror(errno)); | ||
1974 | } | 1969 | } |
1970 | /* detach by removing callback */ | ||
1971 | channel_cancel_cleanup(s->chanid); | ||
1972 | s->chanid = -1; | ||
1975 | session_close(s); | 1973 | session_close(s); |
1976 | } | 1974 | } |
1977 | 1975 | ||
1978 | void | 1976 | void |
1979 | session_close_all(void) | 1977 | session_destroy_all(void) |
1980 | { | 1978 | { |
1981 | int i; | 1979 | int i; |
1982 | for(i = 0; i < MAX_SESSIONS; i++) { | 1980 | for(i = 0; i < MAX_SESSIONS; i++) { |
1983 | Session *s = &sessions[i]; | 1981 | Session *s = &sessions[i]; |
1984 | if (s->used) { | 1982 | if (s->used) |
1985 | if (s->chanid != -1) { | ||
1986 | channel_cancel_cleanup(s->chanid); | ||
1987 | s->chanid = -1; | ||
1988 | } | ||
1989 | session_close(s); | 1983 | session_close(s); |
1990 | } | ||
1991 | } | 1984 | } |
1992 | } | 1985 | } |
1993 | 1986 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: session.h,v 1.12 2001/10/09 21:59:41 markus Exp $ */ | 1 | /* $OpenBSD: session.h,v 1.13 2001/10/10 22:18:47 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -32,6 +32,6 @@ int session_open(Authctxt*, int); | |||
32 | void session_input_channel_req(int, void *); | 32 | void session_input_channel_req(int, void *); |
33 | void session_close_by_pid(pid_t, int); | 33 | void session_close_by_pid(pid_t, int); |
34 | void session_close_by_channel(int, void *); | 34 | void session_close_by_channel(int, void *); |
35 | void session_close_all(void); | 35 | void session_destroy_all(void); |
36 | 36 | ||
37 | #endif | 37 | #endif |