Author: markt
Date: Sat Jul 2 20:48:51 2016
New Revision: 1751096
URL: http://svn.apache.org/viewvc?rev=1751096&view=rev
Log:
Extend synchronization for NIO2 writes to avoid ConcurrentModificationException
observed during testing.
Modified:
tomcat/tc8.0.x/trunk/java/org/apache/coyote/http11/InternalNio2OutputBuffer.java
tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml
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=1751096&r1=1751095&r2=1751096&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
Sat Jul 2 20:48:51 2016
@@ -382,59 +382,59 @@ public class InternalNio2OutputBuffer ex
return false;
ByteBuffer byteBuffer =
socket.getSocket().getBufHandler().getWriteBuffer();
- if (block) {
- if (!isBlocking()) {
- // The final flush is blocking, but the processing was using
- // non blocking so wait until an async write is done
- try {
- if (writePending.tryAcquire(socket.getTimeout(),
TimeUnit.MILLISECONDS)) {
- writePending.release();
+ synchronized (completionHandler) {
+ if (block) {
+ if (!isBlocking()) {
+ // The final flush is blocking, but the processing was
using
+ // non blocking so wait until an async write is done
+ try {
+ if (writePending.tryAcquire(socket.getTimeout(),
TimeUnit.MILLISECONDS)) {
+ writePending.release();
+ }
+ } catch (InterruptedException e) {
+ // Ignore timeout
}
- } catch (InterruptedException e) {
- // Ignore timeout
}
- }
- Future<Integer> future = null;
- try {
- if (bufferedWrites.size() > 0) {
- for (ByteBuffer buffer : bufferedWrites) {
- buffer.flip();
- while (buffer.hasRemaining()) {
- future = socket.getSocket().write(buffer);
- if (future.get(socket.getTimeout(),
TimeUnit.MILLISECONDS).intValue() < 0) {
- throw new
EOFException(sm.getString("iob.failedwrite"));
+ Future<Integer> future = null;
+ try {
+ if (bufferedWrites.size() > 0) {
+ for (ByteBuffer buffer : bufferedWrites) {
+ buffer.flip();
+ while (buffer.hasRemaining()) {
+ future = socket.getSocket().write(buffer);
+ if (future.get(socket.getTimeout(),
TimeUnit.MILLISECONDS).intValue() < 0) {
+ throw new
EOFException(sm.getString("iob.failedwrite"));
+ }
}
}
+ bufferedWrites.clear();
}
- bufferedWrites.clear();
- }
- if (!flipped) {
- byteBuffer.flip();
- flipped = true;
- }
- while (byteBuffer.hasRemaining()) {
- future = socket.getSocket().write(byteBuffer);
- if (future.get(socket.getTimeout(),
TimeUnit.MILLISECONDS).intValue() < 0) {
- throw new
EOFException(sm.getString("iob.failedwrite"));
+ if (!flipped) {
+ byteBuffer.flip();
+ flipped = true;
}
- }
- } catch (ExecutionException e) {
- if (e.getCause() instanceof IOException) {
- throw (IOException) e.getCause();
- } else {
+ while (byteBuffer.hasRemaining()) {
+ future = socket.getSocket().write(byteBuffer);
+ if (future.get(socket.getTimeout(),
TimeUnit.MILLISECONDS).intValue() < 0) {
+ throw new
EOFException(sm.getString("iob.failedwrite"));
+ }
+ }
+ } catch (ExecutionException e) {
+ if (e.getCause() instanceof IOException) {
+ throw (IOException) e.getCause();
+ } else {
+ throw new IOException(e);
+ }
+ } catch (InterruptedException e) {
throw new IOException(e);
+ } catch (TimeoutException e) {
+ future.cancel(true);
+ throw new SocketTimeoutException();
}
- } catch (InterruptedException e) {
- throw new IOException(e);
- } catch (TimeoutException e) {
- future.cancel(true);
- throw new SocketTimeoutException();
- }
- byteBuffer.clear();
- flipped = false;
- return false;
- } else {
- synchronized (completionHandler) {
+ byteBuffer.clear();
+ flipped = false;
+ return false;
+ } else {
if (hasPermit || writePending.tryAcquire()) {
//prevent timeout for async
socket.access();
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=1751096&r1=1751095&r2=1751096&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Sat Jul 2 20:48:51 2016
@@ -89,6 +89,11 @@
<code>InstanceManager.destroy()</code> to ensure that the method is
executed. (markt)
</fix>
+ <fix>
+ Extend synchronization for NIO2 writes to avoid
+ <code>ConcurrentModificationException</code> observed during testing.
+ (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]