Author: markt Date: Mon Jan 12 08:59:48 2015 New Revision: 1651044 URL: http://svn.apache.org/r1651044 Log: Checkpoint - Fix NIO2 deadlock
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java 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=1651044&r1=1651043&r2=1651044&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java Mon Jan 12 08:59:48 2015 @@ -40,6 +40,7 @@ import java.util.concurrent.RejectedExec import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; @@ -714,10 +715,11 @@ public class Nio2Endpoint extends Abstra public static class Nio2SocketWrapper extends SocketWrapperBase<Nio2Channel> { - private static final ThreadLocal<Boolean> writeCompletionInProgress = new ThreadLocal<Boolean>() { + private static final ThreadLocal<AtomicInteger> nestedWriteCompletionCount = + new ThreadLocal<AtomicInteger>() { @Override - protected Boolean initialValue() { - return Boolean.FALSE; + protected AtomicInteger initialValue() { + return new AtomicInteger(0); } }; @@ -787,7 +789,7 @@ public class Nio2Endpoint extends Abstra if (nBytes.intValue() < 0) { failed(new EOFException(sm.getString("iob.failedwrite")), attachment); } else if (Nio2SocketWrapper.this.bufferedWrites.size() > 0) { - writeCompletionInProgress.set(Boolean.TRUE); + nestedWriteCompletionCount.get().incrementAndGet(); // Continue writing data using a gathering write ArrayList<ByteBuffer> arrayList = new ArrayList<>(); if (attachment.hasRemaining()) { @@ -802,13 +804,13 @@ public class Nio2Endpoint extends Abstra Nio2SocketWrapper.this.getSocket().write(array, 0, array.length, Nio2SocketWrapper.this.getTimeout(), TimeUnit.MILLISECONDS, array, gatheringWriteCompletionHandler); - writeCompletionInProgress.set(Boolean.FALSE); + nestedWriteCompletionCount.get().decrementAndGet(); } else if (attachment.hasRemaining()) { // Regular write - writeCompletionInProgress.set(Boolean.TRUE); + nestedWriteCompletionCount.get().incrementAndGet(); Nio2SocketWrapper.this.getSocket().write(attachment, Nio2SocketWrapper.this.getTimeout(), TimeUnit.MILLISECONDS, attachment, writeCompletionHandler); - writeCompletionInProgress.set(Boolean.FALSE); + nestedWriteCompletionCount.get().decrementAndGet(); } else { // All data has been written if (writeInterest) { @@ -820,7 +822,7 @@ public class Nio2Endpoint extends Abstra writeBufferFlipped = false; } } - if (writeNotify && !writeCompletionInProgress.get().booleanValue()) { + if (writeNotify && nestedWriteCompletionCount.get().get() == 0) { endpoint.processSocket(Nio2SocketWrapper.this, SocketStatus.OPEN_WRITE, false); } } @@ -848,7 +850,7 @@ public class Nio2Endpoint extends Abstra failed(new EOFException(sm.getString("iob.failedwrite")), attachment); } else if (Nio2SocketWrapper.this.bufferedWrites.size() > 0 || arrayHasData(attachment)) { // Continue writing data - writeCompletionInProgress.set(Boolean.TRUE); + nestedWriteCompletionCount.get().incrementAndGet(); ArrayList<ByteBuffer> arrayList = new ArrayList<>(); for (ByteBuffer buffer : attachment) { if (buffer.hasRemaining()) { @@ -864,7 +866,7 @@ public class Nio2Endpoint extends Abstra Nio2SocketWrapper.this.getSocket().write(array, 0, array.length, Nio2SocketWrapper.this.getTimeout(), TimeUnit.MILLISECONDS, array, gatheringWriteCompletionHandler); - writeCompletionInProgress.set(Boolean.FALSE); + nestedWriteCompletionCount.get().decrementAndGet(); } else { // All data has been written if (writeInterest) { @@ -876,7 +878,7 @@ public class Nio2Endpoint extends Abstra writeBufferFlipped = false; } } - if (writeNotify && !writeCompletionInProgress.get().booleanValue()) { + if (writeNotify && nestedWriteCompletionCount.get().get() == 0) { endpoint.processSocket(Nio2SocketWrapper.this, SocketStatus.OPEN_WRITE, false); } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org