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

Reply via email to