Author: markt Date: Mon Jul 9 11:58:18 2018 New Revision: 1835413 URL: http://svn.apache.org/viewvc?rev=1835413&view=rev Log: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=62515 When a connector is configured (via setting bindOnInit to false) to bind/unbind the server socket during start/stop, close the socket earlier in the stop process so new connections do not sit in the TCP backlog during the shutdown process only to be dropped as stop completes. In this scenario new connections will now be refused immediately.
Modified: tomcat/trunk/java/org/apache/catalina/core/StandardService.java tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java tomcat/trunk/java/org/apache/coyote/ProtocolHandler.java tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/catalina/core/StandardService.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardService.java?rev=1835413&r1=1835412&r2=1835413&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/StandardService.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/StandardService.java Mon Jul 9 11:58:18 2018 @@ -458,6 +458,9 @@ public class StandardService extends Lif synchronized (connectorsLock) { for (Connector connector: connectors) { connector.pause(); + // Close server socket if bound on start + // Note: test is in AbstractEndpoint + connector.getProtocolHandler().closeServerSocketGraceful(); } } Modified: tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1835413&r1=1835412&r2=1835413&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java (original) +++ tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java Mon Jul 9 11:58:18 2018 @@ -631,6 +631,12 @@ public abstract class AbstractProtocol<S } + @Override + public void closeServerSocketGraceful() { + endpoint.closeServerSocketGraceful(); + } + + // ------------------------------------------- Connection handler base class protected static class ConnectionHandler<S> implements AbstractEndpoint.Handler<S> { Modified: tomcat/trunk/java/org/apache/coyote/ProtocolHandler.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ProtocolHandler.java?rev=1835413&r1=1835412&r2=1835413&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/ProtocolHandler.java (original) +++ tomcat/trunk/java/org/apache/coyote/ProtocolHandler.java Mon Jul 9 11:58:18 2018 @@ -101,6 +101,14 @@ public interface ProtocolHandler { /** + * Close the server socket (to prevent further connections) if the server + * socket was bound on {@link #start()} (rather than on {@link #init()} + * but do not perform any further shutdown. + */ + public void closeServerSocketGraceful(); + + + /** * Requires APR/native library * * @return <code>true</code> if this Protocol Handler requires the Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1835413&r1=1835412&r2=1835413&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java Mon Jul 9 11:58:18 2018 @@ -128,7 +128,7 @@ public abstract class AbstractEndpoint<S } protected enum BindState { - UNBOUND, BOUND_ON_INIT, BOUND_ON_START + UNBOUND, BOUND_ON_INIT, BOUND_ON_START, SOCKET_CLOSED_ON_STOP } @@ -219,7 +219,8 @@ public abstract class AbstractEndpoint<S if (key == null || key.length() == 0) { throw new IllegalArgumentException(sm.getString("endpoint.noSslHostName")); } - if (bindState != BindState.UNBOUND && isSSLEnabled()) { + if (bindState != BindState.UNBOUND && bindState != BindState.SOCKET_CLOSED_ON_STOP && + isSSLEnabled()) { sslHostConfig.setConfigType(getSslConfigType()); try { createSSLContext(sslHostConfig); @@ -1153,7 +1154,7 @@ public abstract class AbstractEndpoint<S public final void stop() throws Exception { stopInternal(); - if (bindState == BindState.BOUND_ON_START) { + if (bindState == BindState.BOUND_ON_START || bindState == BindState.SOCKET_CLOSED_ON_STOP) { unbind(); bindState = BindState.UNBOUND; } @@ -1206,6 +1207,33 @@ public abstract class AbstractEndpoint<S } else return -1; } + + /** + * Close the server socket (to prevent further connections) if the server + * socket was originally bound on {@link #start()} (rather than on + * {@link #init()}). + * + * @see #getBindOnInit() + */ + public final void closeServerSocketGraceful() { + if (bindState == BindState.BOUND_ON_START) { + bindState = BindState.SOCKET_CLOSED_ON_STOP; + try { + doCloseServerSocket(); + } catch (IOException ioe) { + getLog().warn(sm.getString("endpoint.serverSocket.closeFailed", getName()), ioe); + } + } + } + + + /** + * Actually close the server socket but don't perform any other clean-up. + * + * @throws IOException If an error occurs closing the socket + */ + protected abstract void doCloseServerSocket() throws IOException; + protected abstract U serverSocketAccept() throws Exception; protected abstract boolean setSocketOptions(U socket); Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1835413&r1=1835412&r2=1835413&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Mon Jul 9 11:58:18 2018 @@ -92,7 +92,7 @@ public class AprEndpoint extends Abstrac /** * Server socket "pointer". */ - protected long serverSock = 0; + protected volatile long serverSock = 0; /** @@ -774,11 +774,7 @@ public class AprEndpoint extends Abstrac serverSockPool = 0; } - // Close server socket if it was initialised - if (serverSock != 0) { - Socket.close(serverSock); - serverSock = 0; - } + doCloseServerSocket(); if (sslContext != 0) { Long ctx = Long.valueOf(sslContext); @@ -799,6 +795,16 @@ public class AprEndpoint extends Abstrac } + @Override + protected void doCloseServerSocket() { + // Close server socket if it was initialised + if (serverSock != 0) { + Socket.close(serverSock); + serverSock = 0; + } + } + + // ------------------------------------------------------ Protected Methods /** Modified: tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties?rev=1835413&r1=1835412&r2=1835413&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties Mon Jul 9 11:58:18 2018 @@ -67,6 +67,7 @@ endpoint.removeDefaultSslHostConfig=The endpoint.sendfile.addfail=Sendfile failure: [{0}] [{1}] endpoint.sendfile.error=Unexpected sendfile error endpoint.sendfileThreadStop=The sendfile thread failed to stop in a timely manner +endpoint.serverSocket.closeFailed=Failed to close server socket for [{0}] endpoint.setAttribute=Set [{0}] to [{1}] endpoint.timeout.err=Error processing socket timeout endpoint.unknownSslHostName=The SSL host name [{0}] is not recognised for this endpoint 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=1835413&r1=1835412&r2=1835413&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java Mon Jul 9 11:58:18 2018 @@ -70,7 +70,7 @@ public class Nio2Endpoint extends Abstra /** * Server socket "pointer". */ - private AsynchronousServerSocketChannel serverSock = null; + private volatile AsynchronousServerSocketChannel serverSock = null; /** * Allows detecting if a completion handler completes inline. @@ -227,9 +227,7 @@ public class Nio2Endpoint extends Abstra if (running) { stop(); } - // Close server socket - serverSock.close(); - serverSock = null; + doCloseServerSocket(); destroySsl(); super.unbind(); // Unlike other connectors, the thread pool is tied to the server socket @@ -239,6 +237,16 @@ public class Nio2Endpoint extends Abstra } } + + @Override + protected void doCloseServerSocket() throws IOException { + // Close server socket + if (serverSock != null) { + serverSock.close(); + serverSock = null; + } + } + @Override public void shutdownExecutor() { Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1835413&r1=1835412&r2=1835413&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Mon Jul 9 11:58:18 2018 @@ -85,7 +85,7 @@ public class NioEndpoint extends Abstrac /** * Server socket "pointer". */ - private ServerSocketChannel serverSock = null; + private volatile ServerSocketChannel serverSock = null; /** * @@ -328,12 +328,7 @@ public class NioEndpoint extends Abstrac if (running) { stop(); } - if (!getUseInheritedChannel()) { - // Close server socket - serverSock.socket().close(); - serverSock.close(); - } - serverSock = null; + doCloseServerSocket(); destroySsl(); super.unbind(); if (getHandler() != null ) { @@ -346,6 +341,17 @@ public class NioEndpoint extends Abstrac } + @Override + protected void doCloseServerSocket() throws IOException { + if (!getUseInheritedChannel() && serverSock != null) { + // Close server socket + serverSock.socket().close(); + serverSock.close(); + } + serverSock = null; + } + + // ------------------------------------------------------ Protected Methods public NioSelectorPool getSelectorPool() { Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1835413&r1=1835412&r2=1835413&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Mon Jul 9 11:58:18 2018 @@ -88,6 +88,14 @@ <code>Vary</code> HTTP response header to use a common utility method that addresses several additional edge cases. (markt) </fix> + <fix> + <bug>62515</bug>: When a connector is configured (via setting + <code>bindOnInit</code> to <code>false</code>) to bind/unbind the server + socket during start/stop, close the socket earlier in the stop process + so new connections do not sit in the TCP backlog during the shutdown + process only to be dropped as stop completes. In this scenario new + connections will now be refused immediately. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org