Author: remm Date: Fri Apr 27 14:14:22 2018 New Revision: 1830355 URL: http://svn.apache.org/viewvc?rev=1830355&view=rev Log: Fix block read/writes state with NIO2, as most often the calling code with a blocking operation needs to see the result of the state updates done in the completion handler. There's no change in most cases.
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java?rev=1830355&r1=1830354&r2=1830355&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java Fri Apr 27 14:14:22 2018 @@ -904,18 +904,22 @@ public class Nio2Endpoint extends Abstra } } if (complete) { - synchronized (state) { - readPending.release(); - if (state.block == BlockingMode.BLOCK && currentState != CompletionState.INLINE) { - state.state = currentState; - state.notify(); - } else { - state.state = currentState; - } + boolean notify = false; + readPending.release(); + if (state.block == BlockingMode.BLOCK && currentState != CompletionState.INLINE) { + state.state = currentState; + notify = true; + } else { + state.state = currentState; } if (completion && state.handler != null) { state.handler.completed(Long.valueOf(state.nBytes), state.attachment); } + if (notify) { + synchronized (state) { + state.notify(); + } + } } else { getSocket().read(state.buffers, state.offset, state.length, state.timeout, state.unit, state, this); @@ -931,14 +935,14 @@ public class Nio2Endpoint extends Abstra ioe = new IOException(exc); } setError(ioe); - synchronized (state) { - readPending.release(); - if (state.block == BlockingMode.BLOCK) { - state.state = Nio2Endpoint.isInline() ? CompletionState.ERROR : CompletionState.DONE; - state.notify(); - } else { - state.state = Nio2Endpoint.isInline() ? CompletionState.ERROR : CompletionState.DONE; - } + boolean notify = false; + readPending.release(); + readPending.release(); + if (state.block == BlockingMode.BLOCK) { + state.state = Nio2Endpoint.isInline() ? CompletionState.ERROR : CompletionState.DONE; + notify = true; + } else { + state.state = Nio2Endpoint.isInline() ? CompletionState.ERROR : CompletionState.DONE; } if (exc instanceof AsynchronousCloseException) { // If already closed, don't call onError and close again @@ -947,6 +951,11 @@ public class Nio2Endpoint extends Abstra if (state.handler != null) { state.handler.failed(ioe, state.attachment); } + if (notify) { + synchronized (state) { + state.notify(); + } + } } } @@ -973,18 +982,22 @@ public class Nio2Endpoint extends Abstra } } if (complete) { - synchronized (state) { - writePending.release(); - if (state.block == BlockingMode.BLOCK && currentState != CompletionState.INLINE) { - state.state = currentState; - state.notify(); - } else { - state.state = currentState; - } + boolean notify = false; + writePending.release(); + if (state.block == BlockingMode.BLOCK && currentState != CompletionState.INLINE) { + state.state = currentState; + notify = true; + } else { + state.state = currentState; } if (completion && state.handler != null) { state.handler.completed(Long.valueOf(state.nBytes), state.attachment); } + if (notify) { + synchronized (state) { + state.notify(); + } + } } else { getSocket().write(state.buffers, state.offset, state.length, state.timeout, state.unit, state, this); @@ -1000,18 +1013,22 @@ public class Nio2Endpoint extends Abstra ioe = new IOException(exc); } setError(ioe); - synchronized (state) { - writePending.release(); - if (state.block == BlockingMode.BLOCK) { - state.state = Nio2Endpoint.isInline() ? CompletionState.ERROR : CompletionState.DONE; - state.notify(); - } else { - state.state = Nio2Endpoint.isInline() ? CompletionState.ERROR : CompletionState.DONE; - } + boolean notify = false; + writePending.release(); + if (state.block == BlockingMode.BLOCK) { + state.state = Nio2Endpoint.isInline() ? CompletionState.ERROR : CompletionState.DONE; + notify = true; + } else { + state.state = Nio2Endpoint.isInline() ? CompletionState.ERROR : CompletionState.DONE; } if (state.handler != null) { state.handler.failed(ioe, state.attachment); } + if (notify) { + synchronized (state) { + state.notify(); + } + } } } @@ -1024,6 +1041,9 @@ public class Nio2Endpoint extends Abstra handler.failed(ioe, attachment); return CompletionState.ERROR; } + if (timeout == -1) { + timeout = getNio2ReadTimeout(); + } if (block != BlockingMode.NON_BLOCK) { try { if (!readPending.tryAcquire(timeout, unit)) { @@ -1095,6 +1115,9 @@ public class Nio2Endpoint extends Abstra handler.failed(ioe, attachment); return CompletionState.ERROR; } + if (timeout == -1) { + timeout = getNio2WriteTimeout(); + } if (block != BlockingMode.NON_BLOCK) { try { if (!writePending.tryAcquire(timeout, unit)) { Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1830355&r1=1830354&r2=1830355&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Fri Apr 27 14:14:22 2018 @@ -106,6 +106,9 @@ browsers) that do not correctly %nn encode URI paths and query strings as required by RFC 7230 and RFC 3986. (markt) </add> + <fix> + Fix sync for NIO2 async IO blocking read/writes. (remm) + </fix> </changelog> </subsection> <subsection name="Jasper"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org