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