Author: markt Date: Tue Jun 16 13:04:11 2015 New Revision: 1685816 URL: http://svn.apache.org/r1685816 Log: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=57944 Ensure that if either or both of the non-blocking listeners are set on non-container threads that the appropriate events are triggered.
Modified: tomcat/trunk/java/org/apache/catalina/connector/InputBuffer.java tomcat/trunk/java/org/apache/coyote/Response.java tomcat/trunk/test/org/apache/catalina/connector/TestCoyoteOutputStream.java Modified: tomcat/trunk/java/org/apache/catalina/connector/InputBuffer.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/InputBuffer.java?rev=1685816&r1=1685815&r2=1685816&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/connector/InputBuffer.java (original) +++ tomcat/trunk/java/org/apache/catalina/connector/InputBuffer.java Tue Jun 16 13:04:11 2015 @@ -260,6 +260,10 @@ public class InputBuffer extends Reader // is not required. if (!coyoteRequest.isFinished() && isReady()) { coyoteRequest.action(ActionCode.DISPATCH_READ, null); + if (!ContainerThreadMarker.isContainerThread()) { + // Not on a container thread so need to execute the dispatch + coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); + } } } Modified: tomcat/trunk/java/org/apache/coyote/Response.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/Response.java?rev=1685816&r1=1685815&r2=1685816&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/Response.java (original) +++ tomcat/trunk/java/org/apache/coyote/Response.java Tue Jun 16 13:04:11 2015 @@ -581,7 +581,6 @@ public final class Response { // the container will call listener.onWritePossible() once data can be // written. if (isReady()) { - action(ActionCode.DISPATCH_WRITE, null); synchronized (nonBlockingStateLock) { // Ensure we don't get multiple write registrations if // ServletOutputStream.isReady() returns false during a call to @@ -592,6 +591,11 @@ public final class Response { // happen fireListener = true; } + action(ActionCode.DISPATCH_WRITE, null); + if (!ContainerThreadMarker.isContainerThread()) { + // Not on a container thread so need to execute the dispatch + action(ActionCode.DISPATCH_EXECUTE, null); + } } } Modified: tomcat/trunk/test/org/apache/catalina/connector/TestCoyoteOutputStream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/connector/TestCoyoteOutputStream.java?rev=1685816&r1=1685815&r2=1685816&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/connector/TestCoyoteOutputStream.java (original) +++ tomcat/trunk/test/org/apache/catalina/connector/TestCoyoteOutputStream.java Tue Jun 16 13:04:11 2015 @@ -40,43 +40,73 @@ import org.apache.tomcat.util.buf.ByteCh public class TestCoyoteOutputStream extends TomcatBaseTest { @Test - public void testNonBlockingWriteNoneBlockingWriteNone() throws Exception { - doNonBlockingTest(0, 0); + public void testNonBlockingWriteNoneBlockingWriteNoneContainerThread() throws Exception { + doNonBlockingTest(0, 0, true); } @Test - public void testNonBlockingWriteOnceBlockingWriteNone() throws Exception { - doNonBlockingTest(1, 0); + public void testNonBlockingWriteOnceBlockingWriteNoneContainerThread() throws Exception { + doNonBlockingTest(1, 0, true); } @Test - public void testNonBlockingWriteTwiceBlockingWriteNone() throws Exception { - doNonBlockingTest(2, 0); + public void testNonBlockingWriteTwiceBlockingWriteNoneContainerThread() throws Exception { + doNonBlockingTest(2, 0, true); } @Test - public void testNonBlockingWriteNoneBlockingWriteOnce() throws Exception { - doNonBlockingTest(0, 1); + public void testNonBlockingWriteNoneBlockingWriteOnceContainerThread() throws Exception { + doNonBlockingTest(0, 1, true); } @Test - public void testNonBlockingWriteOnceBlockingWriteOnce() throws Exception { - doNonBlockingTest(1, 1); + public void testNonBlockingWriteOnceBlockingWriteOnceContainerThread() throws Exception { + doNonBlockingTest(1, 1, true); } @Test - public void testNonBlockingWriteTwiceBlockingWriteOnce() throws Exception { - doNonBlockingTest(2, 1); + public void testNonBlockingWriteTwiceBlockingWriteOnceContainerThread() throws Exception { + doNonBlockingTest(2, 1, true); } - private void doNonBlockingTest(int asyncWriteTarget, int syncWriteTarget) - throws Exception { + @Test + public void testNonBlockingWriteNoneBlockingWriteNoneNonContainerThread() throws Exception { + doNonBlockingTest(0, 0, false); + } + + @Test + public void testNonBlockingWriteOnceBlockingWriteNoneNonContainerThread() throws Exception { + doNonBlockingTest(1, 0, false); + } + + @Test + public void testNonBlockingWriteTwiceBlockingWriteNoneNonContainerThread() throws Exception { + doNonBlockingTest(2, 0, false); + } + + @Test + public void testNonBlockingWriteNoneBlockingWriteOnceNonContainerThread() throws Exception { + doNonBlockingTest(0, 1, false); + } + + @Test + public void testNonBlockingWriteOnceBlockingWriteOnceNonContainerThread() throws Exception { + doNonBlockingTest(1, 1, false); + } + + @Test + public void testNonBlockingWriteTwiceBlockingWriteOnceNonContainerThread() throws Exception { + doNonBlockingTest(2, 1, false); + } + + private void doNonBlockingTest(int asyncWriteTarget, int syncWriteTarget, + boolean useContainerThreadToSetListener) throws Exception { Tomcat tomcat = getTomcatInstance(); Context root = tomcat.addContext("", TEMP_DIR); Wrapper w = Tomcat.addServlet(root, "nbWrite", - new NonBlockingWriteServlet(asyncWriteTarget)); + new NonBlockingWriteServlet(asyncWriteTarget, useContainerThreadToSetListener)); w.setAsyncSupported(true); root.addServletMapping("/nbWrite", "nbWrite"); Tomcat.addServlet(root, "write", @@ -110,9 +140,12 @@ public class TestCoyoteOutputStream exte private final int asyncWriteTarget; private final AtomicInteger asyncWriteCount = new AtomicInteger(0); + private final boolean useContainerThreadToSetListener; - public NonBlockingWriteServlet(int asyncWriteTarget) { + public NonBlockingWriteServlet(int asyncWriteTarget, + boolean useContainerThreadToSetListener) { this.asyncWriteTarget = asyncWriteTarget; + this.useContainerThreadToSetListener = useContainerThreadToSetListener; } @Override @@ -125,9 +158,14 @@ public class TestCoyoteOutputStream exte AsyncContext asyncCtxt = req.startAsync(); - // Infinite timeout for debugging - asyncCtxt.setTimeout(0); - asyncCtxt.start(new AsyncTask(asyncCtxt, sos)); + asyncCtxt.setTimeout(5); + Runnable task = new AsyncTask(asyncCtxt, sos); + if (useContainerThreadToSetListener) { + asyncCtxt.start(task); + } else { + Thread t = new Thread(task); + t.start(); + } } private void doAsyncWrite(AsyncContext asyncCtxt, --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org