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: [email protected]
For additional commands, e-mail: [email protected]