diff common-session.c @ 419:b2f81110c80b channel-fix

propagate from branch 'au.asn.ucc.matt.dropbear' (head 924b731b50d4147eed8e9382c98a2573259a6cad) to branch 'au.asn.ucc.matt.dropbear.channel-fix' (head e73ee8f7ae404a9355685c30828a0ad4524031bc)
author Matt Johnston <matt@ucc.asn.au>
date Sun, 11 Feb 2007 09:55:00 +0000
parents a01c0c8e543a
children 9c61e7af0156
line wrap: on
line diff
--- a/common-session.c	Sun Feb 11 08:50:21 2007 +0000
+++ b/common-session.c	Sun Feb 11 09:55:00 2007 +0000
@@ -61,6 +61,12 @@
 
 	ses.connecttimeout = 0;
 	
+	if (pipe(ses.signal_pipe) < 0) {
+		dropbear_exit("signal pipe failed");
+	}
+	setnonblocking(ses.signal_pipe[0]);
+	setnonblocking(ses.signal_pipe[1]);
+	
 	kexfirstinitialise(); /* initialise the kex state */
 
 	ses.writepayload = buf_new(MAX_TRANS_PAYLOAD_LEN);
@@ -108,7 +114,6 @@
 
 	ses.allowprivport = 0;
 
-
 	TRACE(("leave session_init"))
 }
 
@@ -132,6 +137,10 @@
 				FD_SET(ses.sock, &writefd);
 			}
 		}
+		
+		/* We get woken up when signal handlers write to this pipe.
+		   SIGCHLD in svr-chansession is the only one currently. */
+		FD_SET(ses.signal_pipe[0], &readfd);
 
 		/* set up for channels which require reading/writing */
 		if (ses.dataallowed) {
@@ -143,27 +152,29 @@
 			dropbear_exit("Terminated by signal");
 		}
 		
-		if (val < 0) {
-			if (errno == EINTR) {
-				/* This must happen even if we've been interrupted, so that
-				 * changed signal-handler vars can take effect etc */
-				if (loophandler) {
-					loophandler();
-				}
-				continue;
-			} else {
-				dropbear_exit("Error in select");
-			}
+		if (val < 0 && errno != EINTR) {
+			dropbear_exit("Error in select");
+		}
+
+		if (val <= 0) {
+			/* If we were interrupted or the select timed out, we still
+			 * want to iterate over channels etc for reading, to handle
+			 * server processes exiting etc. 
+			 * We don't want to read/write FDs. */
+			FD_ZERO(&writefd);
+			FD_ZERO(&readfd);
+		}
+		
+		/* We'll just empty out the pipe if required. We don't do
+		any thing with the data, since the pipe's purpose is purely to
+		wake up the select() above. */
+		if (FD_ISSET(ses.signal_pipe[0], &readfd)) {
+			char x;
+			while (read(ses.signal_pipe[0], &x, 1) > 0) {}
 		}
 
 		/* check for auth timeout, rekeying required etc */
 		checktimeouts();
-		
-		if (val == 0) {
-			/* timeout */
-			TRACE(("select timeout"))
-			continue;
-		}
 
 		/* process session socket's incoming/outgoing data */
 		if (ses.sock != -1) {