summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2001-10-09 21:59:42 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2001-10-09 21:59:42 +0000
commit8cdd0aef6434e6e026b5a375168eeaf1b14919d2 (patch)
tree9889cd3c19b5a4e134070291aa2024259334c406
parent1bed9aad8b2cb1ea27af58b1807d78637109a17b (diff)
simplify session close: no more delayed session_close, no more blocking wait() calls.
-rw-r--r--usr.bin/ssh/channels.c18
-rw-r--r--usr.bin/ssh/channels.h4
-rw-r--r--usr.bin/ssh/serverloop.c38
-rw-r--r--usr.bin/ssh/session.c44
-rw-r--r--usr.bin/ssh/session.h4
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