diff common-channel.c @ 395:dc37bd8563e8 channel-fix

disapproval of revision '5fdf69ca60d1683cdd9f4c2595134bed26394834'
author Matt Johnston <matt@ucc.asn.au>
date Sat, 03 Feb 2007 08:09:22 +0000
parents 17d097fc111c
children a7eb64b9966a
line wrap: on
line diff
--- a/common-channel.c	Sat Feb 03 08:08:47 2007 +0000
+++ b/common-channel.c	Sat Feb 03 08:09:22 2007 +0000
@@ -203,6 +203,24 @@
 				send_msg_channel_data(channel, 1, SSH_EXTENDED_DATA_STDERR);
 		}
 
+		/* 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
+				&& FD_ISSET(channel->writefd, readfds)) {
+			if (channel->initconn) {
+				/* Handling for "in progress" connection - this is needed
+				 * to avoid spinning 100% CPU when we connect to a server
+				 * which doesn't send anything (tcpfwding) */
+				checkinitdone(channel);
+				continue; /* Important not to use the channel after 
+							 checkinitdone(), as it may be NULL */
+			}
+			ret = write(channel->writefd, NULL, 0); /* Fake write */
+			if (ret < 0 && errno != EINTR && errno != EAGAIN) {
+				closewritefd(channel);
+			}
+		}
+
 		/* write to program/pipe stdin */
 		if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
 			if (channel->initconn) {
@@ -427,7 +445,17 @@
 			}
 		}
 
-		/* Stuff from the wire */
+		/* 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) {
+			FD_SET(channel->writefd, readfds);
+		}
+
+		/* Stuff from the wire, to local program/shell/user etc */
 		if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
 				|| channel->initconn) {