Browse Source

StreamCopyThread: Do not let flush interrupt a write

flush calls interrupt() to interrupt a pending read and trigger a
flush.  Unfortunately that interrupt() call can also interrupt a
pending write, putting Jsch in a bad state and triggering "Short read
of block" errors.  Add locking to ensure the flush only interrupts
reads as intended.

Change-Id: Ib105d9e107ae43549ced7e6da29c22ee41cde9d8
stable-4.6
Jonathan Nieder 8 years ago
parent
commit
e67d59df3f
  1. 22
      org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java

22
org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java

@ -61,6 +61,9 @@ public class StreamCopyThread extends Thread {
private final AtomicInteger flushCount = new AtomicInteger(0);
/** Lock held by flush to avoid interrupting a write. */
private final Object writeLock;
/**
* Create a thread to copy data from an input stream to an output stream.
*
@ -75,6 +78,7 @@ public class StreamCopyThread extends Thread {
setName(Thread.currentThread().getName() + "-StreamCopy"); //$NON-NLS-1$
src = i;
dst = o;
writeLock = new Object();
}
/**
@ -86,8 +90,10 @@ public class StreamCopyThread extends Thread {
*/
public void flush() {
flushCount.incrementAndGet();
synchronized (writeLock) {
interrupt();
}
}
/**
* Request that the thread terminate, and wait for it.
@ -118,12 +124,12 @@ public class StreamCopyThread extends Thread {
for (;;) {
try {
if (readInterrupted) {
try {
synchronized (writeLock) {
boolean interruptedAgain = Thread.interrupted();
dst.flush();
} catch (InterruptedIOException e) {
// There was a new flush() call during flush previous bytes
// need continue read/write/flush for the new bytes
continue;
if (interruptedAgain) {
interrupt();
}
}
readInterrupted = false;
if (!flushCount.compareAndSet(flushCountBeforeRead, 0)) {
@ -148,6 +154,11 @@ public class StreamCopyThread extends Thread {
if (n < 0)
break;
synchronized (writeLock) {
if (isInterrupted()) {
continue;
}
boolean writeInterrupted = false;
for (;;) {
try {
@ -163,6 +174,7 @@ public class StreamCopyThread extends Thread {
interrupt();
break;
}
}
} catch (IOException e) {
break;
}

Loading…
Cancel
Save