Author: markt
Date: Tue Sep 17 09:58:30 2013
New Revision: 1523967
URL: http://svn.apache.org/r1523967
Log:
Improve handling of situation where socket / connector closes down while an
application thread is using the socket. This ismost likely to occur with
upgraded connections that use concurrent read/write (e.g. WebSocket)
Modified:
tomcat/tc7.0.x/trunk/ (props changed)
tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AprServletOutputStream.java
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/res/LocalStrings.properties
Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
Merged /tomcat/trunk:r1523964
Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1523967&r1=1523966&r2=1523967&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java Tue Sep
17 09:58:30 2013
@@ -675,6 +675,7 @@ public abstract class AbstractProtocol i
} else {
// Connection closed. OK to recycle the processor. Upgrade
// processors are not recycled.
+ wrapper.setClosing(true);
connections.remove(socket);
if (processor.isUpgrade()) {
processor.getHttpUpgradeHandler().destroy();
Modified:
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java?rev=1523967&r1=1523966&r2=1523967&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java
Tue Sep 17 09:58:30 2013
@@ -27,6 +27,7 @@ import org.apache.juli.logging.LogFactor
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.AprEndpoint;
import org.apache.tomcat.util.net.AprEndpoint.Handler;
+import org.apache.tomcat.util.net.AprEndpoint.Poller;
import org.apache.tomcat.util.net.SocketStatus;
import org.apache.tomcat.util.net.SocketWrapper;
@@ -279,8 +280,13 @@ public class Http11AprProtocol extends A
}
} else if (processor.isUpgrade()) {
// Upgraded
- ((AprEndpoint) proto.endpoint).getPoller().add(
- socket.getSocket().longValue(), -1, true, false);
+ Poller p = ((AprEndpoint) proto.endpoint).getPoller();
+ if (p == null) {
+ // Connector has been stopped
+ release(socket, processor, true, false);
+ } else {
+ p.add(socket.getSocket().longValue(), -1, true, false);
+ }
} else {
// Tomcat 7 proprietary upgrade
((AprEndpoint) proto.endpoint).getPoller().add(
Modified:
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java?rev=1523967&r1=1523966&r2=1523967&view=diff
==============================================================================
---
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java
(original)
+++
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java
Tue Sep 17 09:58:30 2013
@@ -50,7 +50,7 @@ public class AprServletInputStream exten
try {
readLock.lock();
if (wrapper.getBlockingStatus() == block) {
- if (closed) {
+ if (closed || wrapper.isClosing()) {
throw new IOException(sm.getString("apr.closed"));
}
result = Socket.recv(socket, b, off, len);
@@ -70,7 +70,7 @@ public class AprServletInputStream exten
try {
readLock.lock();
writeLock.unlock();
- if (closed) {
+ if (closed || wrapper.isClosing()) {
throw new IOException(sm.getString("apr.closed"));
}
result = Socket.recv(socket, b, off, len);
Modified:
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AprServletOutputStream.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AprServletOutputStream.java?rev=1523967&r1=1523966&r2=1523967&view=diff
==============================================================================
---
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AprServletOutputStream.java
(original)
+++
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/upgrade/AprServletOutputStream.java
Tue Sep 17 09:58:30 2013
@@ -60,7 +60,7 @@ public class AprServletOutputStream exte
try {
readLock.lock();
if (wrapper.getBlockingStatus() == block) {
- if (closed) {
+ if (closed || wrapper.isClosing()) {
throw new IOException(sm.getString("apr.closed"));
}
return doWriteInternal(b, off, len);
@@ -83,7 +83,7 @@ public class AprServletOutputStream exte
try {
readLock.lock();
writeLock.unlock();
- if (closed) {
+ if (closed || wrapper.isClosing()) {
throw new IOException(sm.getString("apr.closed"));
}
return doWriteInternal(b, off, len);
Modified:
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1523967&r1=1523966&r2=1523967&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
Tue Sep 17 09:58:30 2013
@@ -504,6 +504,18 @@ public abstract class AbstractEndpoint {
//this is our internal one, so we need to shut it down
ThreadPoolExecutor tpe = (ThreadPoolExecutor) executor;
tpe.shutdownNow();
+ int count = 0;
+ while (count < 50 && tpe.isTerminating()) {
+ try {
+ Thread.sleep(100);
+ count++;
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ if (tpe.isTerminating()) {
+
getLog().warn(sm.getString("endpoint.warn.executorShutdown", getName()));
+ }
TaskQueue queue = (TaskQueue) tpe.getQueue();
queue.setParent(null);
}
Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1523967&r1=1523966&r2=1523967&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Tue
Sep 17 09:58:30 2013
@@ -1585,6 +1585,10 @@ public class AprEndpoint extends Abstrac
}
}
+ if (!pollerRunning) {
+ break;
+ }
+
try {
// Add sockets which are waiting to the poller
if (addList.size() > 0) {
Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1523967&r1=1523966&r2=1523967&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Tue
Sep 17 09:58:30 2013
@@ -1511,13 +1511,12 @@ public class NioEndpoint extends Abstrac
}
public void reset(Poller poller, NioChannel channel, long soTimeout) {
- this.socket = channel;
+ super.reset(channel, soTimeout);
+
+ cometNotify = false;
+ cometOps = SelectionKey.OP_READ;
+ interestOps = 0;
this.poller = poller;
- lastAccess = System.currentTimeMillis();
- setComet(false);
- timeout = soTimeout;
- setWriteTimeout(soTimeout);
- error = false;
lastRegistered = 0;
sendfileData = null;
if (readLatch != null) {
@@ -1529,6 +1528,7 @@ public class NioEndpoint extends Abstrac
}
}
readLatch = null;
+ sendfileData = null;
if (writeLatch != null) {
try {
for (int i = 0; i < (int) writeLatch.getCount(); i++) {
@@ -1538,11 +1538,7 @@ public class NioEndpoint extends Abstrac
}
}
writeLatch = null;
- cometNotify = false;
- cometOps = SelectionKey.OP_READ;
- sendfileData = null;
- keepAliveLeft = 100;
- async = false;
+ setWriteTimeout(soTimeout);
}
public void reset() {
Modified:
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java?rev=1523967&r1=1523966&r2=1523967&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java Tue
Sep 17 09:58:30 2013
@@ -52,6 +52,17 @@ public class SocketWrapper<E> {
*/
private final Object writeThreadLock = new Object();
+ /*
+ * Used to indicate that the socket is in the process of closing / has been
+ * closed. Once this flag has been set, no further reads or writes should
+ * take place. Its primary purpose is with upgraded connections where a
+ * socket may be in use in application code with no immediate way to signal
+ * that the socket is no longer valid. Checking this flag before any
+ * application triggered read or write will enable an IOException to be
+ * thrown.
+ */
+ private boolean closing = false;
+
public SocketWrapper(E socket) {
this.socket = socket;
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
@@ -89,4 +100,19 @@ public class SocketWrapper<E> {
return blockingStatusWriteLock;
}
public Object getWriteThreadLock() { return writeThreadLock; }
+ public boolean isClosing() { return closing; }
+ public void setClosing(boolean closing) { this.closing = closing; }
+
+ public void reset(E socket, long timeout) {
+ async = false;
+ blockingStatus = true;
+ closing = false;
+ comet = false;
+ error = false;
+ keepAliveLeft = 100;
+ lastAccess = System.currentTimeMillis();
+ this.socket = socket;
+ this.timeout = timeout;
+ upgraded = false;
+ }
}
Modified:
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/res/LocalStrings.properties
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/res/LocalStrings.properties?rev=1523967&r1=1523966&r2=1523967&view=diff
==============================================================================
---
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/res/LocalStrings.properties
(original)
+++
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/res/LocalStrings.properties
Tue Sep 17 09:58:30 2013
@@ -22,6 +22,7 @@ endpoint.warn.noDisableCompression='Disa
endpoint.warn.noHonorCipherOrder='Honor cipher order' option is not supported
by the SSL library {0}
endpoint.warn.noInsecureReneg=Secure re-negotiation is not supported by the
SSL library {0}
endpoint.warn.unlockAcceptorFailed=Acceptor thread [{0}] failed to unlock.
Forcing hard socket shutdown.
+endpoint.warn.executorShutdown=The executor associated with thread pool [{0}]
has not fully shutdown. Some application threads may still be running.
endpoint.debug.channelCloseFail=Failed to close channel
endpoint.debug.destroySocket=socket [{0}], doIt [{1}]
endpoint.debug.pollerAdd=socket [{0}], timeout [{1}], flags [{2}]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]