Index: java/org/apache/coyote/http11/InternalInputBuffer.java =================================================================== --- java/org/apache/coyote/http11/InternalInputBuffer.java (revision 1711641) +++ java/org/apache/coyote/http11/InternalInputBuffer.java (working copy) @@ -76,7 +76,7 @@ * tested for == 0 or > 0. */ @Override - public int available() { + public int available(boolean read) { return 1; } Index: java/org/apache/coyote/http11/AbstractHttp11Processor.java =================================================================== --- java/org/apache/coyote/http11/AbstractHttp11Processor.java (revision 1711641) +++ java/org/apache/coyote/http11/AbstractHttp11Processor.java (working copy) @@ -873,7 +873,7 @@ break; } case AVAILABLE: { - request.setAvailable(inputBuffer.available()); + request.setAvailable(inputBuffer.available(param == Boolean.TRUE)); break; } case NB_WRITE_INTEREST: { Index: java/org/apache/catalina/connector/InputBuffer.java =================================================================== --- java/org/apache/catalina/connector/InputBuffer.java (revision 1711641) +++ java/org/apache/catalina/connector/InputBuffer.java (working copy) @@ -241,7 +241,7 @@ available = cb.getLength(); } if (available == 0) { - coyoteRequest.action(ActionCode.AVAILABLE, null); + coyoteRequest.action(ActionCode.AVAILABLE, Boolean.valueOf(coyoteRequest.getReadListener() != null)); available = (coyoteRequest.getAvailable() > 0) ? 1 : 0; } return available; Index: java/org/apache/tomcat/util/net/Nio2Channel.java =================================================================== --- java/org/apache/tomcat/util/net/Nio2Channel.java (revision 1711641) +++ java/org/apache/tomcat/util/net/Nio2Channel.java (working copy) @@ -26,6 +26,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.net.SecureNio2Channel.ApplicationBufferHandler; /** @@ -35,6 +37,7 @@ */ public class Nio2Channel implements AsynchronousByteChannel { + private static final Log log = LogFactory.getLog(Nio2Channel.class); protected static ByteBuffer emptyBuf = ByteBuffer.allocate(0); protected AsynchronousSocketChannel sc = null; @@ -128,9 +131,21 @@ return super.toString()+":"+this.sc.toString(); } + private volatile Exception stack = null; @Override public Future read(ByteBuffer dst) { - return sc.read(dst); + Exception previous = stack; + try { + throw new Exception(Thread.currentThread().getName()); + } catch (Exception e) { + stack = e; + } + try { + return sc.read(dst); + } catch (java.nio.channels.ReadPendingException e) { + log.error("Read pending exception, previous read stack was: ", previous); + throw e; + } } @Override @@ -142,6 +157,11 @@ public void read(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, CompletionHandler handler) { + try { + throw new Exception(Thread.currentThread().getName()); + } catch (Exception e) { + stack = e; + } sc.read(dst, timeout, unit, attachment, handler); } Index: java/org/apache/coyote/http11/AbstractInputBuffer.java =================================================================== --- java/org/apache/coyote/http11/AbstractInputBuffer.java (revision 1711641) +++ java/org/apache/coyote/http11/AbstractInputBuffer.java (working copy) @@ -326,7 +326,7 @@ * Available bytes in the buffers (note that due to encoding, this may not * correspond). */ - public int available() { + public int available(boolean read) { int available = lastValid - pos; if ((available == 0) && (lastActiveFilter >= 0)) { for (int i = 0; (available == 0) && (i <= lastActiveFilter); i++) { @@ -337,17 +337,19 @@ return available; } - try { - fill(false); - available = lastValid - pos; - } catch (IOException ioe) { - if (getLog().isDebugEnabled()) { - getLog().debug(sm.getString("iib.available.readFail"), ioe); + if (read) { + try { + fill(false); + available = lastValid - pos; + } catch (IOException ioe) { + if (getLog().isDebugEnabled()) { + getLog().debug(sm.getString("iib.available.readFail"), ioe); + } + // Not ideal. This will indicate that data is available which should + // trigger a read which in turn will trigger another IOException and + // that one can be thrown. + available = 1; } - // Not ideal. This will indicate that data is available which should - // trigger a read which in turn will trigger another IOException and - // that one can be thrown. - available = 1; } return available; }