Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

#57 Concurrent bugs on channel.isClosed()

open
nobody
None
5
2013-01-18
2013-01-18
Liu Feifei
No

I wrote a test class for concurrent executing SSH commands on a remote server (CentOS).
But most of times I got incorrect results.
Code example:
for (int i=0; i<size; i++) {
new Thread() {
public void run() {
runAndWait("uname -a", session);
}
}.start();
}

And in side the thread function, the channel is created and data is read (from JSCH example):

byte[] tmp=new byte[1024];
while(true){ /////(1)
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0) {
break;
}
System.out.print(Thread.currentThread().getName() + " " + new String(tmp, 0, i));
}
if(channel.isClosed()){ //////(2)
System.out.println("exit-status: "+ channel.getExitStatus());
break;
}
try{
Thread.sleep(10);
} catch(Exception ee){
}
}
channel.disconnect();

By debugging, I found that for some threads, the in.available() is always 0. After a few iterations in (1), the channel.isClosed() at (2) is true. So the (1) breaks; and nothing is got.

To walk around this case, I made changes to my code: If channel.isClosed(), read the stream ONCE MORE. Now it works:

boolean last = false; ////last means, the channel is closed. But there may be data in the stream. Needs to read it for the last time.

while(true) {
int size = in.available();
while (size > 0) {
int i = in.read(tmp, 0, 1024);
System.out.println(Thread.currentThread().getName() + " read " + i + " bytes");
if (i < 0) {
break;
}
bos.write(tmp, 0, i);
size = in.available();
}

if (last) {
break;
}

if (!last && channel.isClosed()) {
System.out.println(Thread.currentThread().getName() + " exit-status: " + channel.getExitStatus());
last = true;
}
}

I suspect that there is a bug inside the JSCH channel stream and connection status management code: The connection status is set to "closed" before the data is pipled into the stream.

So the channel is closed; but there is data left in the sream.

Discussion