Author: remm Date: Thu Oct 29 18:19:58 2015 New Revision: 1711315 URL: http://svn.apache.org/viewvc?rev=1711315&view=rev Log: Cancel pending blocking IO operation following a timeout in the NIO2 connector.
Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2InputBuffer.java tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletInputStream.java tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2InputBuffer.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2InputBuffer.java?rev=1711315&r1=1711314&r2=1711315&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2InputBuffer.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2InputBuffer.java Thu Oct 29 18:19:58 2015 @@ -22,6 +22,7 @@ import java.net.SocketTimeoutException; import java.nio.ByteBuffer; import java.nio.channels.CompletionHandler; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -219,9 +220,10 @@ public class InternalNio2InputBuffer ext } else { byteBuffer.clear(); flipped = false; + Future<Integer> future = null; try { - nRead = socket.getSocket().read(byteBuffer) - .get(socket.getTimeout(), TimeUnit.MILLISECONDS).intValue(); + future = socket.getSocket().read(byteBuffer); + nRead = future.get(socket.getTimeout(), TimeUnit.MILLISECONDS).intValue(); } catch (ExecutionException e) { if (e.getCause() instanceof IOException) { throw (IOException) e.getCause(); @@ -231,6 +233,9 @@ public class InternalNio2InputBuffer ext } catch (InterruptedException e) { throw new IOException(e); } catch (TimeoutException e) { + if (future != null) { + future.cancel(true); + } throw new SocketTimeoutException(); } if (nRead > 0) { Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java?rev=1711315&r1=1711314&r2=1711315&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java Thu Oct 29 18:19:58 2015 @@ -24,6 +24,7 @@ import java.nio.ByteBuffer; import java.nio.channels.CompletionHandler; import java.util.ArrayList; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -393,12 +394,14 @@ public class InternalNio2OutputBuffer ex // Ignore timeout } } + Future<Integer> future = null; try { if (bufferedWrites.size() > 0) { for (ByteBuffer buffer : bufferedWrites) { buffer.flip(); while (buffer.hasRemaining()) { - if (socket.getSocket().write(buffer).get(socket.getTimeout(), TimeUnit.MILLISECONDS).intValue() < 0) { + future = socket.getSocket().write(buffer); + if (future.get(socket.getTimeout(), TimeUnit.MILLISECONDS).intValue() < 0) { throw new EOFException(sm.getString("iob.failedwrite")); } } @@ -410,7 +413,8 @@ public class InternalNio2OutputBuffer ex flipped = true; } while (byteBuffer.hasRemaining()) { - if (socket.getSocket().write(byteBuffer).get(socket.getTimeout(), TimeUnit.MILLISECONDS).intValue() < 0) { + future = socket.getSocket().write(byteBuffer); + if (future.get(socket.getTimeout(), TimeUnit.MILLISECONDS).intValue() < 0) { throw new EOFException(sm.getString("iob.failedwrite")); } } @@ -423,6 +427,9 @@ public class InternalNio2OutputBuffer ex } catch (InterruptedException e) { throw new IOException(e); } catch (TimeoutException e) { + if (future != null) { + future.cancel(true); + } throw new SocketTimeoutException(); } byteBuffer.clear(); Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletInputStream.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletInputStream.java?rev=1711315&r1=1711314&r2=1711315&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletInputStream.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletInputStream.java Thu Oct 29 18:19:58 2015 @@ -23,6 +23,7 @@ import java.nio.ByteBuffer; import java.nio.channels.AsynchronousCloseException; import java.nio.channels.CompletionHandler; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -189,9 +190,10 @@ public class Nio2ServletInputStream exte readPending = true; readBuffer.clear(); flipped = false; + Future<Integer> future = null; try { - nRead = channel.read(readBuffer) - .get(wrapper.getTimeout(), TimeUnit.MILLISECONDS).intValue(); + future = channel.read(readBuffer); + nRead = future.get(wrapper.getTimeout(), TimeUnit.MILLISECONDS).intValue(); readPending = false; } catch (ExecutionException e) { if (e.getCause() instanceof IOException) { @@ -205,6 +207,9 @@ public class Nio2ServletInputStream exte onError(e); throw new IOException(e); } catch (TimeoutException e) { + if (future != null) { + future.cancel(true); + } SocketTimeoutException ex = new SocketTimeoutException(); onError(ex); throw ex; Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java?rev=1711315&r1=1711314&r2=1711315&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java Thu Oct 29 18:19:58 2015 @@ -23,6 +23,7 @@ import java.nio.ByteBuffer; import java.nio.channels.AsynchronousCloseException; import java.nio.channels.CompletionHandler; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -122,8 +123,10 @@ public class Nio2ServletOutputStream ext buffer.clear(); buffer.put(b, off, len); buffer.flip(); + Future<Integer> future = null; try { - written = channel.write(buffer).get(socketWrapper.getTimeout(), TimeUnit.MILLISECONDS).intValue(); + future = channel.write(buffer); + written = future.get(socketWrapper.getTimeout(), TimeUnit.MILLISECONDS).intValue(); } catch (ExecutionException e) { if (e.getCause() instanceof IOException) { onError(e.getCause()); @@ -136,6 +139,9 @@ public class Nio2ServletOutputStream ext onError(e); throw new IOException(e); } catch (TimeoutException e) { + if (future != null) { + future.cancel(true); + } SocketTimeoutException ex = new SocketTimeoutException(); onError(ex); throw ex; @@ -156,11 +162,13 @@ public class Nio2ServletOutputStream ext @Override protected void doFlush() throws IOException { + Future<Boolean> future = null; try { // Block until a possible non blocking write is done if (writePending.tryAcquire(socketWrapper.getTimeout(), TimeUnit.MILLISECONDS)) { writePending.release(); - channel.flush().get(socketWrapper.getTimeout(), TimeUnit.MILLISECONDS); + future = channel.flush(); + future.get(socketWrapper.getTimeout(), TimeUnit.MILLISECONDS); } else { throw new TimeoutException(); } @@ -176,6 +184,9 @@ public class Nio2ServletOutputStream ext onError(e); throw new IOException(e); } catch (TimeoutException e) { + if (future != null) { + future.cancel(true); + } SocketTimeoutException ex = new SocketTimeoutException(); onError(ex); throw ex; Modified: tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java?rev=1711315&r1=1711314&r2=1711315&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java Thu Oct 29 18:19:58 2015 @@ -495,7 +495,7 @@ public class SecureNio2Channel extends N private class FutureRead implements Future<Integer> { private final ByteBuffer dst; - private final Future<Integer> integer; + private Future<Integer> integer; public FutureRead(ByteBuffer dst) { this.dst = dst; if (netInBuffer.position() > 0) { @@ -521,6 +521,9 @@ public class SecureNio2Channel extends N public Integer get() throws InterruptedException, ExecutionException { try { return (integer == null) ? unwrap(netInBuffer.position(), -1, TimeUnit.MILLISECONDS) : unwrap(integer.get().intValue(), -1, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + // Cannot happen: no timeout + throw new ExecutionException(e); } finally { readPending = false; } @@ -535,7 +538,7 @@ public class SecureNio2Channel extends N readPending = false; } } - private Integer unwrap(int nRead, long timeout, TimeUnit unit) throws ExecutionException { + private Integer unwrap(int nRead, long timeout, TimeUnit unit) throws ExecutionException, InterruptedException, TimeoutException { //are we in the middle of closing or closed? if (closing || closed) return Integer.valueOf(-1); @@ -567,14 +570,11 @@ public class SecureNio2Channel extends N //if we need more network data, then bail out for now. if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { if (read == 0) { - try { - if (timeout > 0) { - return unwrap(sc.read(netInBuffer).get(timeout, unit).intValue(), timeout, unit); - } else { - return unwrap(sc.read(netInBuffer).get().intValue(), -1, TimeUnit.MILLISECONDS); - } - } catch (InterruptedException | TimeoutException e) { - throw new ExecutionException(e); + integer = sc.read(netInBuffer); + if (timeout > 0) { + return unwrap(integer.get(timeout, unit).intValue(), timeout, unit); + } else { + return unwrap(integer.get().intValue(), -1, TimeUnit.MILLISECONDS); } } else { break; Modified: tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml?rev=1711315&r1=1711314&r2=1711315&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Thu Oct 29 18:19:58 2015 @@ -123,6 +123,14 @@ </fix> </changelog> </subsection> + <subsection name="Coyote"> + <changelog> + <fix> + Cancel pending blocking IO operation following a timeout in the NIO2 + connector. (remm) + </fix> + </changelog> + </subsection> <subsection name="Cluster"> <changelog> <fix> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org