You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2010/12/09 20:49:25 UTC

svn commit: r1044110 - in /tomcat/trunk: java/org/apache/tomcat/util/net/ test/org/apache/tomcat/util/net/ webapps/docs/ webapps/docs/config/

Author: markt
Date: Thu Dec  9 19:49:24 2010
New Revision: 1044110

URL: http://svn.apache.org/viewvc?rev=1044110&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=50360
Add an option to control when the socket is bound

Modified:
    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/JIoEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
    tomcat/trunk/test/org/apache/tomcat/util/net/TestXxxEndpoint.java
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/docs/config/http.xml

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=1044110&r1=1044109&r2=1044110&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java Thu Dec  9 19:49:24 2010
@@ -97,6 +97,10 @@ public abstract class AbstractEndpoint {
         public void recycle();
     }
 
+    protected enum BindState {
+        UNBOUND, BOUND_ON_INIT, BOUND_ON_START
+    }
+
     // Standard SSL Configuration attributes
     // JSSE
     // Standard configuration attribute names
@@ -143,11 +147,6 @@ public abstract class AbstractEndpoint {
     protected volatile boolean paused = false;
 
     /**
-     * Track the initialization state of the endpoint.
-     */
-    protected boolean initialized = false;
-
-    /**
      * Are we using an internal executor
      */
     protected volatile boolean internalExecutor = false;
@@ -202,6 +201,17 @@ public abstract class AbstractEndpoint {
     public int getBacklog() { return backlog; }
 
     /**
+     * Controls when the Endpoint binds the port. <code>true</code>, the default
+     * binds the port on {@link #init()} and unbinds it on {@link #destroy()}.
+     * If set to <code>false</code> the port is bound on {@link #start()} and
+     * unbound on {@link #stop()}.  
+     */
+    private boolean bindOnInit = true;
+    public boolean getBindOnInit() { return bindOnInit; }
+    public void setBindOnInit(boolean b) { this.bindOnInit = b; }
+    private BindState bindState = BindState.UNBOUND;
+
+    /**
      * Keepalive timeout, if lesser or equal to 0 then soTimeout will be used.
      */
     private int keepAliveTimeout = -1;
@@ -503,8 +513,34 @@ public abstract class AbstractEndpoint {
     }
 
 
-    public abstract void init() throws Exception;
-    public abstract void start() throws Exception;
+    // ------------------------------------------------------- Lifecycle methods
+
+    /*
+     * NOTE: There is no maintenance of state or checking for valid transitions
+     * within this class other than ensuring that bind/unbind are called in the
+     * right place. It is expected that the calling code will maintain state and
+     * prevent invalid state transitions.
+     */
+
+    public abstract void bind() throws Exception;
+    public abstract void unbind() throws Exception;
+    public abstract void startInternal() throws Exception;
+    public abstract void stopInternal() throws Exception;
+
+    public final void init() throws Exception {
+        if (bindOnInit) {
+            bind();
+            bindState = BindState.BOUND_ON_INIT;
+        }
+    }
+    
+    public final void start() throws Exception {
+        if (bindState == BindState.UNBOUND) {
+            bind();
+            bindState = BindState.BOUND_ON_START;
+        }
+        startInternal();
+    }
 
     /**
      * Pause the endpoint, which will stop it accepting new connections.
@@ -532,8 +568,21 @@ public abstract class AbstractEndpoint {
         }
     }
 
-    public abstract void stop() throws Exception;
-    public abstract void destroy() throws Exception;
+    public final void stop() throws Exception {
+        stopInternal();
+        if (bindState == BindState.BOUND_ON_START) {
+            unbind();
+            bindState = BindState.UNBOUND;
+        }
+    }
+
+    public final void destroy() throws Exception {
+        if (bindState == BindState.BOUND_ON_INIT) {
+            unbind();
+            bindState = BindState.UNBOUND;
+        }
+    }
+
 
     public String adjustRelativePath(String path, String relativeTo) {
         String newPath = path;

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=1044110&r1=1044109&r2=1044110&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Thu Dec  9 19:49:24 2010
@@ -365,11 +365,7 @@ public class AprEndpoint extends Abstrac
      * Initialize the endpoint.
      */
     @Override
-    public void init()
-        throws Exception {
-
-        if (initialized)
-            return;
+    public void bind() throws Exception {
 
         // Create the root APR memory pool
         try {
@@ -518,9 +514,6 @@ public class AprEndpoint extends Abstrac
             // For now, sendfile is not supported with SSL
             useSendfile = false;
         }
-
-        initialized = true;
-
     }
 
 
@@ -528,12 +521,8 @@ public class AprEndpoint extends Abstrac
      * Start the APR endpoint, creating acceptor, poller and sendfile threads.
      */
     @Override
-    public void start()
-        throws Exception {
-        // Initialize socket if not done before
-        if (!initialized) {
-            init();
-        }
+    public void startInternal() throws Exception {
+
         if (!running) {
             running = true;
             paused = false;
@@ -602,7 +591,7 @@ public class AprEndpoint extends Abstrac
      * Stop the endpoint. This will cause all processing threads to stop.
      */
     @Override
-    public void stop() {
+    public void stopInternal() {
         if (!paused) {
             pause();
         }
@@ -665,7 +654,7 @@ public class AprEndpoint extends Abstrac
      * Deallocate APR memory pools, and close server socket.
      */
     @Override
-    public void destroy() throws Exception {
+    public void unbind() throws Exception {
         if (running) {
             stop();
         }
@@ -691,8 +680,6 @@ public class AprEndpoint extends Abstrac
         }
 
         handler.recycle();
-
-        initialized = false;
     }
 
 

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java?rev=1044110&r1=1044109&r2=1044110&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java Thu Dec  9 19:49:24 2010
@@ -324,12 +324,8 @@ public class JIoEndpoint extends Abstrac
     // -------------------- Public methods --------------------
 
     @Override
-    public void init()
-        throws Exception {
+    public void bind() throws Exception {
 
-        if (initialized)
-            return;
-        
         // Initialize thread count defaults for acceptor
         if (acceptorThreadCount == 0) {
             acceptorThreadCount = 1;
@@ -365,15 +361,11 @@ public class JIoEndpoint extends Abstrac
             }
         }
         
-        initialized = true;
     }
     
     @Override
-    public void start() throws Exception {
-        // Initialize socket if not done before
-        if (!initialized) {
-            init();
-        }
+    public void startInternal() throws Exception {
+
         if (!running) {
             running = true;
             paused = false;
@@ -402,7 +394,7 @@ public class JIoEndpoint extends Abstrac
     }
 
     @Override
-    public void stop() {
+    public void stopInternal() {
         if (!paused) {
             pause();
         }
@@ -417,7 +409,7 @@ public class JIoEndpoint extends Abstrac
      * Deallocate APR memory pools, and close server socket.
      */
     @Override
-    public void destroy() throws Exception {
+    public void unbind() throws Exception {
         if (running) {
             stop();
         }
@@ -431,7 +423,6 @@ public class JIoEndpoint extends Abstrac
             serverSocket = null;
         }
         handler.recycle();
-        initialized = false ;
     }
 
 

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=1044110&r1=1044109&r2=1044110&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Thu Dec  9 19:49:24 2010
@@ -455,11 +455,7 @@ public class NioEndpoint extends Abstrac
      * Initialize the endpoint.
      */
     @Override
-    public void init()
-        throws Exception {
-
-        if (initialized)
-            return;
+    public void bind() throws Exception {
 
         serverSock = ServerSocketChannel.open();
         socketProperties.setProperties(serverSock.socket());
@@ -545,8 +541,6 @@ public class NioEndpoint extends Abstrac
         
         if (oomParachute>0) reclaimParachute(true);
         selectorPool.open();
-        initialized = true;
-
     }
     
     public KeyManager[] wrap(KeyManager[] managers) {
@@ -567,12 +561,8 @@ public class NioEndpoint extends Abstrac
      * Start the NIO endpoint, creating acceptor, poller threads.
      */
     @Override
-    public void start()
-        throws Exception {
-        // Initialize socket if not done before
-        if (!initialized) {
-            init();
-        }
+    public void startInternal() throws Exception {
+
         if (!running) {
             running = true;
             paused = false;
@@ -607,7 +597,7 @@ public class NioEndpoint extends Abstrac
      * Stop the endpoint. This will cause all processing threads to stop.
      */
     @Override
-    public void stop() {
+    public void stopInternal() {
         if (!paused) {
             pause();
         }
@@ -634,7 +624,7 @@ public class NioEndpoint extends Abstrac
      * Deallocate NIO memory pools, and close server socket.
      */
     @Override
-    public void destroy() throws Exception {
+    public void unbind() throws Exception {
         if (log.isDebugEnabled()) {
             log.debug("Destroy initiated for "+new InetSocketAddress(getAddress(),getPort()));
         }
@@ -646,7 +636,6 @@ public class NioEndpoint extends Abstrac
         serverSock.close();
         serverSock = null;
         sslContext = null;
-        initialized = false;
         releaseCaches();
         selectorPool.close();
         if (log.isDebugEnabled()) {

Modified: tomcat/trunk/test/org/apache/tomcat/util/net/TestXxxEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/net/TestXxxEndpoint.java?rev=1044110&r1=1044109&r2=1044110&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/net/TestXxxEndpoint.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/util/net/TestXxxEndpoint.java Thu Dec  9 19:49:24 2010
@@ -20,6 +20,7 @@ package org.apache.tomcat.util.net;
 import java.io.File;
 import java.net.ServerSocket;
 
+import org.apache.catalina.connector.Connector;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.catalina.startup.TomcatBaseTest;
 
@@ -29,7 +30,7 @@ import org.apache.catalina.startup.Tomca
  */
 public class TestXxxEndpoint extends TomcatBaseTest {
 
-    public void disbaletestStartStop() throws Exception {
+    public void testStartStopBindOnInit() throws Exception {
         Tomcat tomcat = getTomcatInstance();
         File appDir = new File(getBuildDirectory(), "webapps/examples");
         tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath());
@@ -39,13 +40,52 @@ public class TestXxxEndpoint extends Tom
         tomcat.start();
         
         tomcat.getConnector().stop();
-        // This will throw an exception if the socket is not released
-        ServerSocket socket = new ServerSocket(port);
-        socket.close();
+        // This will should throw an Exception
+        Exception e = null;
+        ServerSocket s = null;
+        try {
+            s = new ServerSocket(port);
+        } catch (Exception e1) {
+            e = e1;
+        } finally {
+            if (s != null) {
+                try {
+                    s.close();
+                } catch (Exception e2) { /* Ignore */ }
+            }
+        }
+        assertNotNull(e);
         tomcat.getConnector().start();
     }
-    
-    public void testDummy() throws Exception {
-        // NO-OP
+
+    public void testStartStopBindOnStart() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+        Connector c = tomcat.getConnector();
+        c.setProperty("bindOnInit", "false");
+        
+        File appDir = new File(getBuildDirectory(), "webapps/examples");
+        tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath());
+        
+        int port = getPort();
+
+        tomcat.start();
+        
+        tomcat.getConnector().stop();
+        // This should not throw an Exception
+        Exception e = null;
+        ServerSocket s = null;
+        try {
+            s = new ServerSocket(port);
+        } catch (Exception e1) {
+            e = e1;
+        } finally {
+            if (s != null) {
+                try {
+                    s.close();
+                } catch (Exception e2) { /* Ignore */ }
+            }
+        }
+        assertNull(e);
+        tomcat.getConnector().start();
     }
 }

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1044110&r1=1044109&r2=1044110&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Thu Dec  9 19:49:24 2010
@@ -130,6 +130,16 @@
         <bug>50108</bug>: Add get/set methods for Connector property
         minSpareThreads. Patch provided by Eiji Takahashi. (markt)
       </add>
+      <fix>
+        <bug>50360</bug>:  Provide an option to control when the socket
+        associated with a connector is bound. By default, the socket is bound on
+        <code>Connector.init()</code> and released on
+        <code>Connector.destroy()</code> as per the current behaviour but this
+        can be changed so that the socket is bound on
+        <code>Connector.start()</code> and released on
+        <code>Connector.stop()</code>. This fix also includes further Lifecycle
+        refactoring for Connectors and associated components. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Jasper">

Modified: tomcat/trunk/webapps/docs/config/http.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/http.xml?rev=1044110&r1=1044109&r2=1044110&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/http.xml (original)
+++ tomcat/trunk/webapps/docs/config/http.xml Thu Dec  9 19:49:24 2010
@@ -265,6 +265,13 @@
       associated with the server.</p>
     </attribute>
 
+    <attribute name="bindOnInit" required="false">
+      <p>Controls when the socket used by the connector is bound. By default it
+      is bound when the connector is initiated and unbund when the connector is
+      destroyed. If set to <code>false</code>, the socket will be bound when the
+      connector is started and unbound when it is stopped.</p>
+    </attribute>
+
     <attribute name="compressableMimeType" required="false">
       <p>The value is a comma separated list of MIME types for which HTTP
       compression may be used.



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org