From 8ccbd216c61539e4d2d7add7be5efd78fb9a9864 Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Tue, 29 Sep 2015 21:53:27 +0800
Subject: [PATCH] make sure that the test for queued packets to write occurs
 after those packets might have been enqueued by set_connect_fds()

---
 common-session.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/common-session.c b/common-session.c
index 2485cd82..96d747db 100644
--- a/common-session.c
+++ b/common-session.c
@@ -159,6 +159,16 @@ void session_loop(void(*loophandler)()) {
 		FD_ZERO(&readfd);
 		dropbear_assert(ses.payload == NULL);
 
+		/* 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 can be read/written */
+		setchannelfds(&readfd, &writefd, writequeue_has_space);
+
+		/* Pending connections to test */
+		set_connect_fds(&writefd);
+
 		/* We delay reading from the input socket during initial setup until
 		after we have written out our initial KEXINIT packet (empty writequeue). 
 		This means our initial packet can be in-flight while we're doing a blocking
@@ -170,19 +180,12 @@ void session_loop(void(*loophandler)()) {
 			&& writequeue_has_space) {
 			FD_SET(ses.sock_in, &readfd);
 		}
+
+		/* Ordering is important, this test must occur after any other function
+		might have queued packets (such as connection handlers) */
 		if (ses.sock_out != -1 && !isempty(&ses.writequeue)) {
 			FD_SET(ses.sock_out, &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 can be read/written */
-		setchannelfds(&readfd, &writefd, writequeue_has_space);
-
-		/* Pending connections to test */
-		set_connect_fds(&writefd);
 
 		val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout);
 
-- 
GitLab