summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2007-02-03 08:09:22 +0000
committerMatt Johnston <matt@ucc.asn.au>2007-02-03 08:09:22 +0000
commit41bfa930580c0f81f953cd94340b84e793b14591 (patch)
treedc6bece4692049393b3d3ffd4990629c2c502ff5
parent056b92bd4c8a42ce1843493310d382159166edb8 (diff)
disapproval of revision '5fdf69ca60d1683cdd9f4c2595134bed26394834'
--HG-- branch : channel-fix extra : convert_revision : b24757c764465a206a258bae27ac0509fc56cd16
-rw-r--r--common-channel.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/common-channel.c b/common-channel.c
index 7e8d428..54829e5 100644
--- a/common-channel.c
+++ b/common-channel.c
@@ -203,6 +203,24 @@ void channelio(fd_set *readfds, fd_set *writefds) {
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 @@ void setchannelfds(fd_set *readfds, fd_set *writefds) {
}
}
- /* 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) {