changeset 331:d6b8815a9b5e

progress towards exiting on writefd closure rather than on process exit - dbclient hangs with scp, so requires work.
author Matt Johnston <matt@ucc.asn.au>
date Sun, 11 Jun 2006 16:19:32 +0000
parents 5488db2e9e4e
children 6f90e5fd42cc e7c1a77d2921
files common-channel.c svr-chansession.c
diffstat 2 files changed, 29 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/common-channel.c	Sat Jun 10 16:39:40 2006 +0000
+++ b/common-channel.c	Sun Jun 11 16:19:32 2006 +0000
@@ -181,6 +181,7 @@
 
 	struct Channel *channel;
 	unsigned int i;
+	int ret;
 
 	/* iterate through all the possible channels */
 	for (i = 0; i < ses.chansize; i++) {
@@ -204,7 +205,8 @@
 
 		/* if we can read from the writefd, it might be closed, so we try to
 		 * see if it has errors */
-		if (channel->writefd >= 0 && channel->writefd != channel->readfd
+		if (IS_DROPBEAR_SERVER && channel->writefd >= 0 
+				&& channel->writefd != channel->readfd
 				&& FD_ISSET(channel->writefd, readfds)) {
 			if (channel->initconn) {
 				/* Handling for "in progress" connection - this is needed
@@ -259,27 +261,27 @@
 				channel->writebuf,
 				channel->writebuf ? 0 : cbuf_getused(channel->extrabuf)))
 
-	if (!channel->sentclosed) {
-
-		/* check for exited - currently only used for server sessions,
-		 * if the shell has exited etc */
-		if (channel->type->checkclose) {
-			if (channel->type->checkclose(channel)) {
-				closewritefd(channel);
-			}
+	/* server chansession channels are special, since readfd mightn't
+	 * close in the case of "sleep 4 & echo blah" until the sleep is up */
+	if (channel->type->checkclose) {
+		if (channel->type->checkclose(channel)) {
+			closewritefd(channel);
+			closereadfd(channel, channel->readfd);
+			closereadfd(channel, channel->errfd);
 		}
+	}
 
-		if (!channel->senteof
-			&& channel->readfd == FD_CLOSED 
-			&& (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) {
-			send_msg_channel_eof(channel);
-		}
+	if (!channel->senteof
+		&& channel->readfd == FD_CLOSED 
+		&& (channel->extrabuf == NULL || channel->errfd == FD_CLOSED)) {
+		send_msg_channel_eof(channel);
+	}
 
-		if (channel->writefd == FD_CLOSED
-			&& channel->readfd == FD_CLOSED
-			&& (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) {
-			send_msg_channel_close(channel);
-		}
+	if (!channel->sentclosed
+		&& channel->writefd == FD_CLOSED
+		&& channel->readfd == FD_CLOSED
+		&& (channel->extrabuf == NULL || channel->errfd == FD_CLOSED)) {
+		send_msg_channel_close(channel);
 	}
 
 	/* When either party wishes to terminate the channel, it sends
@@ -444,20 +446,22 @@
 			}
 		}
 
-		/* For checking FD status (ie closure etc) - we don't actually
-		 * read data from writefd */
 		TRACE(("writefd = %d, readfd %d, errfd %d, bufused %d", 
 					channel->writefd, channel->readfd,
 					channel->errfd,
 					cbuf_getused(channel->writebuf) ))
-		if (channel->writefd >= 0 && channel->writefd != channel->readfd) {
+
+		/* For checking FD status (ie closure etc) - we don't actually
+		 * read data from writefd. We don't want to do this for the client,
+		 * since redirection to /dev/null will make it spin in the select */
+		if (IS_DROPBEAR_SERVER && channel->writefd >= 0 
+				&& channel->writefd != channel->readfd) {
 			FD_SET(channel->writefd, readfds);
 		}
 
-		/* Stuff from the wire, to local program/shell/user etc */
+		/* Stuff from the wire */
 		if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
 				|| channel->initconn) {
-
 				FD_SET(channel->writefd, writefds);
 		}
 
--- a/svr-chansession.c	Sat Jun 10 16:39:40 2006 +0000
+++ b/svr-chansession.c	Sun Jun 11 16:19:32 2006 +0000
@@ -67,8 +67,7 @@
 extern char** environ;
 
 static int sesscheckclose(struct Channel *channel) {
-	struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
-	return chansess->exit.exitpid >= 0;
+	return channel->writefd == -1;
 }
 
 /* Handler for childs exiting, store the state for return to the client */