FELIX-3456 Track how lock was obtained, and try to do a thread dump on lock problems

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1371288 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/pom.xml b/scr/pom.xml
index 7d05057..1698d37 100644
--- a/scr/pom.xml
+++ b/scr/pom.xml
@@ -331,6 +331,9 @@
                         <ignore>java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock</ignore>
                         <ignore>java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock</ignore>
                         <ignore>java.util.concurrent.TimeUnit</ignore>
+                        <ignore>java.lang.management.ManagementFactory</ignore>
+                        <ignore>java.lang.management.ThreadInfo</ignore>
+                        <ignore>java.lang.management.ThreadMXBean</ignore>
                     </ignores>
                 </configuration>
                 <executions>
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index 97b5265..732ba01 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -18,6 +18,9 @@
  */
 package org.apache.felix.scr.impl.manager;
 
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
 import java.security.Permission;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -31,7 +34,6 @@
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
-import EDU.oswego.cs.dl.util.concurrent.ReaderPreferenceReadWriteLock;
 import org.apache.felix.scr.Component;
 import org.apache.felix.scr.Reference;
 import org.apache.felix.scr.impl.BundleComponentActivator;
@@ -97,6 +99,9 @@
 
     private long m_timeout = 5000;
 
+    private Thread lockingThread;
+    private Throwable lockingStackTrace;
+
     /**
      * The constructor receives both the activator and the metadata
      *
@@ -162,7 +167,15 @@
         {
             if (!m_stateLock.tryReadLock( m_timeout ) )
             {
-                throw new IllegalStateException( "Could not obtain lock in " + m_timeout + " milliseconds for component " + m_componentMetadata.getName() );
+                try
+                {
+                    dumpThreads();
+                }
+                catch ( Throwable e )
+                {
+                     //we are on a pre 1.6 vm, no worries
+                }
+                throw ( IllegalStateException ) new IllegalStateException( "Could not obtain lock in " + m_timeout + " milliseconds for component " + m_componentMetadata.getName() ).initCause( lockingStackTrace );
             }
         }
         catch ( InterruptedException e )
@@ -188,6 +201,8 @@
             {
                 throw new IllegalStateException( "Could not obtain lock" );
             }
+            lockingThread = Thread.currentThread();
+            lockingStackTrace = new Exception("Write lock stack trace for thread: " + lockingThread);
         }
         catch ( InterruptedException e )
         {
@@ -199,6 +214,8 @@
     final void deescalateLock()
     {
         m_stateLock.deescalate();
+        lockingThread = null;
+        lockingStackTrace = null;
     }
 
     final void checkLocked()
@@ -214,6 +231,18 @@
         return m_stateLock.getWriteHoldCount() > 0;
     }
 
+    private void dumpThreads()
+    {
+        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+        StringBuffer b = new StringBuffer( "Thread dump\n" );
+        ThreadInfo[] infos = threadMXBean.dumpAllThreads( threadMXBean.isObjectMonitorUsageSupported(), threadMXBean.isSynchronizerUsageSupported() );
+        for ( int i = 0; i < infos.length; i++ )
+        {
+            b.append( infos[i] ).append( "\n\n" );
+        }
+        log( LogService.LOG_INFO, b.toString(), null );
+    }
+
 //---------- Component ID management
 
     void registerComponentId()