You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pa...@apache.org on 2014/07/09 11:56:54 UTC

svn commit: r1609073 - /felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java

Author: pauls
Date: Wed Jul  9 09:56:54 2014
New Revision: 1609073

URL: http://svn.apache.org/r1609073
Log:
Fix a deadlock in URLHandlers when Felix.init and Felix.stop are called concurrently (FELIX-4523).

Modified:
    felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java?rev=1609073&r1=1609072&r2=1609073&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java Wed Jul  9 09:56:54 2014
@@ -87,7 +87,7 @@ class URLHandlers implements URLStreamHa
 
     // This maps classloaders of URLHandlers in other classloaders to lists of
     // their frameworks.
-    private static Map m_classloaderToFrameworkLists = new HashMap();
+    private final static Map m_classloaderToFrameworkLists = new HashMap();
 
     // The list to hold all enabled frameworks registered with this handlers
     private static final List m_frameworks = new ArrayList();
@@ -586,6 +586,7 @@ class URLHandlers implements URLStreamHa
     **/
     public static void registerFrameworkInstance(Object framework, boolean enable)
     {
+        boolean register = false;
         synchronized (m_frameworks)
         {
             // If the URL Handlers service is not going to be enabled,
@@ -595,13 +596,38 @@ class URLHandlers implements URLStreamHa
                 // We need to create an instance if this is the first
                 // time this method is called, which will set the handler
                 // factories.
-                if (m_handler == null)
+                if (m_handler == null )
                 {
-                    m_handler = new URLHandlers();
+                    register = true;
+                }
+                else
+                {
+                    m_frameworks.add(framework);
+                    m_counter++;
+                }
+            }
+            else
+            {
+                m_counter++;
+            }
+        }
+        if (register)
+        {
+            synchronized (URL.class)
+            {
+                synchronized (m_classloaderToFrameworkLists)
+                {
+                    synchronized (m_frameworks)
+                    {
+                        if (m_handler == null )
+                        {
+                            m_handler = new URLHandlers();
+                        }
+                        m_frameworks.add(framework);
+                        m_counter++;
+                    }
                 }
-                m_frameworks.add(framework);
             }
-            m_counter++;
         }
     }
 
@@ -618,32 +644,55 @@ class URLHandlers implements URLStreamHa
         boolean unregister = false;
         synchronized (m_frameworks)
         {
-            m_counter--;
-            if (m_frameworks.remove(framework))
+            if (m_frameworks.contains(framework))
             {
-                if (m_frameworks.isEmpty())
+                if (m_frameworks.size() == 1 && m_handler != null)
                 {
                     unregister = true;
-                    m_handler = null;
+                }
+                else
+                {
+                    m_frameworks.remove(framework);
+                    m_counter--;
                 }
             }
+            else
+            {
+                m_counter--;
+            }
         }
         if (unregister)
         {
-             try
-             {
-                 m_secureAction.invoke(m_secureAction.getDeclaredMethod(
-                     m_rootURLHandlers.getClass(),
-                     "unregisterFrameworkListsForContextSearch",
-                     new Class[]{ ClassLoader.class}),
-                     m_rootURLHandlers,
-                     new Object[] {URLHANDLERS_CLASS.getClassLoader()});
-             }
-             catch (Exception e)
-             {
-                 // This should not happen
-                 e.printStackTrace();
-             }
+            synchronized (URL.class)
+            {
+                synchronized (m_classloaderToFrameworkLists)
+                {
+                    synchronized (m_frameworks)
+                    {
+                        m_frameworks.remove(framework);
+                        m_counter--;
+                        if (m_frameworks.isEmpty() && m_handler != null)
+                        {
+
+                            m_handler = null;
+                            try
+                            {
+                                m_secureAction.invoke(m_secureAction.getDeclaredMethod(
+                                    m_rootURLHandlers.getClass(),
+                                    "unregisterFrameworkListsForContextSearch",
+                                    new Class[]{ ClassLoader.class}),
+                                    m_rootURLHandlers,
+                                    new Object[] {URLHANDLERS_CLASS.getClassLoader()});
+                            }
+                            catch (Exception e)
+                            {
+                                // This should not happen
+                                e.printStackTrace();
+                            }
+                        }
+                    }
+                }
+            }
         }
     }