Deadlocks in ExpectOutputStream

Per Allansson per@appgate.com
Fri, 16 Jan 2004 09:54:36 +0100


Try the following patch - it should fix the problem with the stream
hanging on large outputs. I don't know about you other problem, though -
maybe you could construct a small example that shows the problem?

/p


---------------------------------------------------------------------------
Index: com/mindbright/ssh2/SSH2Channel.java
===================================================================
RCS file: 
/usr/site/share/cvsroot/mindterm/src/com/mindbright/ssh2/SSH2Channel.java,v
retrieving revision 1.12
retrieving revision 1.14
diff -u -r1.12 -r1.14
--- com/mindbright/ssh2/SSH2Channel.java	2003/07/09 12:32:55	1.12
+++ com/mindbright/ssh2/SSH2Channel.java	2003/10/30 09:54:43	1.14
@@ -315,11 +315,11 @@
       */
      protected final synchronized void sendClose() {
  	if(!closeSent) {
+	    closeSent = true;
  	    SSH2TransportPDU pdu =
  		SSH2TransportPDU.createOutgoingPacket(SSH2.MSG_CHANNEL_CLOSE);
  	    pdu.writeInt(peerChanId);
  	    connection.transmit(pdu);
-	    closeSent = true;
  	}
  	checkTermination();
      }
Index: com/mindbright/ssh2/SSH2SessionChannel.java
===================================================================
RCS file: 
/usr/site/share/cvsroot/mindterm/src/com/mindbright/ssh2/SSH2SessionChannel.java,v
retrieving revision 1.9
retrieving revision 1.11
diff -u -r1.9 -r1.11
--- com/mindbright/ssh2/SSH2SessionChannel.java	2003/07/07 04:59:51	1.9
+++ com/mindbright/ssh2/SSH2SessionChannel.java	2003/11/18 13:11:51	1.11
@@ -52,9 +52,9 @@
      protected SSH2SessionChannel(SSH2Connection connection) {
  	super(SSH2Connection.CH_TYPE_SESSION, connection);

-	this.rxInitWinSz = 16384;
-	this.rxCurrWinSz = 16384;
-	this.rxMaxPktSz  = 4096;
+	this.rxInitWinSz = 16*1024;
+	this.rxCurrWinSz = 16*1024;
+	this.rxMaxPktSz  = 4*1024;
  	this.started     = false;
  	this.exited      = false;
  	this.blocking    = true;
@@ -287,23 +287,26 @@
  	    connection.getLog().error("SSH2SessionChannel", "extData",
  				      "extended data of unknown type: " + type);
  	} else {
-	    try {
+ 	    try {
+
  		int    len  = pdu.readInt();
  		byte[] data = pdu.getData();
  		int    off  = pdu.getRPos();
-		if(stderrW != null) {
-		    stderrW.write(data, off, len);
-		} else {
-		    connection.getLog().debug("SSH2SessionChannel",
-					      "session " + "(ch. #" + channelId +
-					      ") stderr : " +
-					      new String(data, off, len));
-		}
-	    } catch (IOException e) {
-		connection.getLog().error("SSH2SessionChannel", "extData",
-					  "error writing to stderr: " +
-					  e.getMessage());
-	    }
+                rxCounter += len;
+ 		if(stderrW != null) {
+ 		    stderrW.write(data, off, len);
+ 		} else {
+ 		    connection.getLog().debug("SSH2SessionChannel",
+ 					      "session " + "(ch. #" + channelId +
+ 					      ") stderr : " +
+ 					      new String(data, off, len));
+ 		}
+                checkRxWindowSize(len);
+ 	    } catch (IOException e) {
+ 		connection.getLog().error("SSH2SessionChannel", "extData",
+ 					  "error writing to stderr: " +
+ 					  e.getMessage());
+ 	    }
  	}
      }

Index: com/mindbright/ssh2/SSH2StreamChannel.java
===================================================================
RCS file: 
/usr/site/share/cvsroot/mindterm/src/com/mindbright/ssh2/SSH2StreamChannel.java,v
retrieving revision 1.10
retrieving revision 1.13
diff -u -r1.10 -r1.13
--- com/mindbright/ssh2/SSH2StreamChannel.java	2003/07/09 12:32:55	1.10
+++ com/mindbright/ssh2/SSH2StreamChannel.java	2003/11/18 13:11:51	1.13
@@ -94,7 +94,7 @@
  	    int              maxSz = 0;
  	    int              rcvSz = 0;
              boolean          interrupted = false;
-	    while(!eofSent) {
+	    while(!eofSent && !closeSent) {
  		pdu =
  		    SSH2TransportPDU.createOutgoingPacket(SSH2.MSG_CHANNEL_DATA,
  							  txMaxPktSz + 256);
@@ -102,15 +102,15 @@
  		maxSz = checkTxWindowSize(rcvSz);
                  do {
                      try {
-                            rcvSz = in.read(pdu.data, pdu.wPos + 4, maxSz);
-                            interrupted = false;
+                        rcvSz = in.read(pdu.data, pdu.wPos + 4, maxSz);
+                        interrupted = false;
                      } catch (InterruptedIOException e) {
-                            interrupted = true;
+                        interrupted = true;
                      }
                  } while (interrupted);
  		if(rcvSz == -1) {
  		    sendEOF();
-		} else {
+		} else if (!eofSent && !closeSent) {
  		    pdu.writeInt(rcvSz);
  		    pdu.wPos  += rcvSz;
  		    txCounter += rcvSz;
@@ -205,7 +205,7 @@
  	return dataSz;
      }

-    private final void checkRxWindowSize(int len) {
+    protected final void checkRxWindowSize(int len) {
  	rxCurrWinSz -= len;
  	if(rxCurrWinSz < 0) {
  	    connection.fatalDisconnect(SSH2.DISCONNECT_PROTOCOL_ERROR,
---------------------------------------------------------------------------

Matthew White wrote:
> Hi,
> 
>  
> 
>             I have been trying to figure out a few problems relating to
> the RemoteShellScript example code. I have written an application which
> directly calls the run method of RemoteShellScript, and I have run into
> at least 2 nasty bugs regarding synchronization. The first bug that I
> encountered was when a large amount of output was received from the
> command that I was executing. After a certain number of messages, output
> would hang, and so would the code. I managed to work around this by
> preventing the code from producing the large amount of output (an error
> was causing the output). Now, I am encountering a situation where
> somehow either the end marker is received out of sequence, or it is not
> received at all (I can't tell which), and, as a result, the application
> hangs. It is odd because I have made MANY successful calls prior to this
> problematic one with no problems, and I have even made the exact same
> call once previously on the machine. Any idea what could be happening or
> how I can fix it?
> 
>  
> 
> Thanks in advance,
> 
> Matt
> 
>