Author: markt
Date: Wed Sep  3 13:41:05 2014
New Revision: 1622253

URL: http://svn.apache.org/r1622253
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56905
Make destruction on web application stop of thread group used for WebSocket 
connections more robust.
Patch by kkolinko with minor tweaks

Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties
    
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java
    tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
  Merged /tomcat/trunk:r1622251

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties?rev=1622253&r1=1622252&r2=1622253&view=diff
==============================================================================
--- 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties
 (original)
+++ 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties
 Wed Sep  3 13:41:05 2014
@@ -24,7 +24,7 @@ serverContainer.missingEndpoint=An Endpo
 serverContainer.pojoDeploy=POJO class [{0}] deploying to path [{1}] in 
ServletContext [{2}]
 serverContainer.servletContextMismatch=Attempted to register a POJO annotated 
for WebSocket at path [{0}] in the ServletContext with context path [{1}] when 
the WebSocket ServerContainer is allocated to the ServletContext with context 
path [{2}]
 serverContainer.servletContextMissing=No ServletContext was specified
-serverContainer.threadGroupNotDestroyed=Unable to destroy WebSocket thread 
group [{0}] as some threads were still running when the web application was 
stopped
+serverContainer.threadGroupNotDestroyed=Unable to destroy WebSocket thread 
group [{0}] as [{1}] threads were still running when the web application was 
stopped. The thread group will be destroyed once the threads terminate.
 
 uriTemplate.duplicateParameter=The parameter [{0}] appears more than once in 
the path which is not permitted
 uriTemplate.emptySegment=The path [{0}] contains one or more empty segments 
which are is not permitted

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java?rev=1622253&r1=1622252&r2=1622253&view=diff
==============================================================================
--- 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java
 (original)
+++ 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java
 Wed Sep  3 13:41:05 2014
@@ -276,14 +276,42 @@ public class WsServerContainer extends W
     public void destroy() {
         shutdownExecutor();
         super.destroy();
+        // If the executor hasn't fully shutdown it won't be possible to
+        // destroy this thread group as there will still be threads running.
+        // Mark the thread group as daemon one, so that it destroys itself
+        // when thread count reaches zero.
+        // Synchronization on threadGroup is needed, as there is a race between
+        // destroy() call from termination of the last thread in thread group
+        // marked as daemon versus the explicit destroy() call.
+        int threadCount = threadGroup.activeCount();
+        boolean success = false;
         try {
-            threadGroup.destroy();
-        } catch (IllegalThreadStateException itse) {
-            // If the executor hasn't fully shutdown it won't be possible to
-            // destroy this thread group as there will still be threads running
-            log.warn(sm.getString("serverContainer.threadGroupNotDestroyed",
-                    threadGroup.getName()));
+            while (true) {
+                int oldThreadCount = threadCount;
+                synchronized (threadGroup) {
+                    if (threadCount > 0) {
+                        Thread.yield();
+                        threadCount = threadGroup.activeCount();
+                    }
+                    if (threadCount > 0 && threadCount != oldThreadCount) {
+                        // Value not stabilized. Retry.
+                        continue;
+                    }
+                    if (threadCount > 0) {
+                        threadGroup.setDaemon(true);
+                    } else {
+                        threadGroup.destroy();
+                        success = true;
+                    }
+                    break;
+                }
+            }
+        } catch (IllegalThreadStateException exception) {
+            // Fall-through
         }
+        if (!success) {
+            log.warn(sm.getString("serverContainer.threadGroupNotDestroyed",
+                    threadGroup.getName(), Integer.valueOf(threadCount)));     
   }
     }
 
 

Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1622253&r1=1622252&r2=1622253&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Wed Sep  3 13:41:05 2014
@@ -169,6 +169,10 @@
         application. (markt) 
       </fix>
       <fix>
+        <bug>56905</bug>: Make destruction on web application stop of thread
+        group used for WebSocket connections more robust. (kkolinko/markt)
+      </fix>
+      <fix>
         <bug>56907</bug>: Ensure that client IO threads are stopped if a secure
         WebSocket client connection fails. (markt)
       </fix>



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

Reply via email to