Author: rjung
Date: Thu May  6 19:17:49 2010
New Revision: 941868

URL: http://svn.apache.org/viewvc?rev=941868&view=rev
Log:
BZ48903: Fix deadlock in webapp class loader.
Backport of r927565 and r927877 from trunk.
Already applied to TC 5.5 as r935947.

Modified:
    tomcat/tc6.0.x/trunk/STATUS.txt
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/ResourceEntry.java
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java
    tomcat/tc6.0.x/trunk/java/org/apache/jasper/servlet/JasperLoader.java
    tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml

Modified: tomcat/tc6.0.x/trunk/STATUS.txt
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=941868&r1=941867&r2=941868&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/STATUS.txt (original)
+++ tomcat/tc6.0.x/trunk/STATUS.txt Thu May  6 19:17:49 2010
@@ -142,28 +142,6 @@ PATCHES PROPOSED TO BACKPORT:
 
   kkolinko: We have to mention the new parameter in 
jasper-howto.html#Configuration
 
-* Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=48903
-  and https://issues.apache.org/bugzilla/show_bug.cgi?id=48694#c8
-  Fix deadlock /sync issues in WebappClassLoader. Revert to using
-  synchronized(this) as analysis and experience shows anything else will just
-  cause problems
-  The patch looks huge but it just removes the sync block and sync's the method
-  http://svn.apache.org/viewvc?rev=927565&view=rev
-  svn diff -x -w -r927564:927565 http://svn.apache.org/repos/asf/tomcat/trunk
-  +1: markt, kkolinko, rjung
-  -1: 
-
-  Additional patch:
-  Mark ResourceEntry.loadedClass as volatile.
-  http://svn.apache.org/viewvc?rev=927877&view=rev
-  +1: kkolinko, markt, rjung
-  -1:
-
-  Note: (kkolinko): Applied to 5.5.x in r935947. The above patches address
-  BZ 44041, BZ 48903, BZ 48694. Those three issues are to be marked as 
RESOLVED,
-  when these patches are applied.
-
-
 * Correct SSL session timeout attribute name
   http://people.apache.org/~markt/patches/2010-04-07-SslSessionTimeout.patch
   +1: markt

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/ResourceEntry.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/ResourceEntry.java?rev=941868&r1=941867&r2=941868&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/ResourceEntry.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/ResourceEntry.java Thu 
May  6 19:17:49 2010
@@ -47,7 +47,7 @@ public class ResourceEntry {
     /**
      * Loaded class.
      */
-    public Class loadedClass = null;
+    public volatile Class loadedClass = null;
 
 
     /**

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java?rev=941868&r1=941867&r2=941868&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java 
Thu May  6 19:17:49 2010
@@ -1432,102 +1432,121 @@ public class WebappClassLoader
      *
      * @exception ClassNotFoundException if the class was not found
      */
-    public Class loadClass(String name, boolean resolve)
+    public synchronized Class loadClass(String name, boolean resolve)
         throws ClassNotFoundException {
 
-        synchronized (name.intern()) {
-            if (log.isDebugEnabled())
-                log.debug("loadClass(" + name + ", " + resolve + ")");
-            Class clazz = null;
-    
-            // Log access to stopped classloader
-            if (!started) {
-                try {
-                    throw new IllegalStateException();
-                } catch (IllegalStateException e) {
-                    log.info(sm.getString("webappClassLoader.stopped", name), 
e);
-                }
+        if (log.isDebugEnabled())
+            log.debug("loadClass(" + name + ", " + resolve + ")");
+        Class clazz = null;
+
+        // Log access to stopped classloader
+        if (!started) {
+            try {
+                throw new IllegalStateException();
+            } catch (IllegalStateException e) {
+                log.info(sm.getString("webappClassLoader.stopped", name), e);
             }
-    
-            // (0) Check our previously loaded local class cache
-            clazz = findLoadedClass0(name);
+        }
+
+        // (0) Check our previously loaded local class cache
+        clazz = findLoadedClass0(name);
+        if (clazz != null) {
+            if (log.isDebugEnabled())
+                log.debug("  Returning class from cache");
+            if (resolve)
+                resolveClass(clazz);
+            return (clazz);
+        }
+
+        // (0.1) Check our previously loaded class cache
+        clazz = findLoadedClass(name);
+        if (clazz != null) {
+            if (log.isDebugEnabled())
+                log.debug("  Returning class from cache");
+            if (resolve)
+                resolveClass(clazz);
+            return (clazz);
+        }
+
+        // (0.2) Try loading the class with the system class loader, to prevent
+        //       the webapp from overriding J2SE classes
+        try {
+            clazz = system.loadClass(name);
             if (clazz != null) {
-                if (log.isDebugEnabled())
-                    log.debug("  Returning class from cache");
                 if (resolve)
                     resolveClass(clazz);
                 return (clazz);
             }
-    
-            // (0.1) Check our previously loaded class cache
-            clazz = findLoadedClass(name);
-            if (clazz != null) {
-                if (log.isDebugEnabled())
-                    log.debug("  Returning class from cache");
-                if (resolve)
-                    resolveClass(clazz);
-                return (clazz);
+        } catch (ClassNotFoundException e) {
+            // Ignore
+        }
+
+        // (0.5) Permission to access this class when using a SecurityManager
+        if (securityManager != null) {
+            int i = name.lastIndexOf('.');
+            if (i >= 0) {
+                try {
+                    securityManager.checkPackageAccess(name.substring(0,i));
+                } catch (SecurityException se) {
+                    String error = "Security Violation, attempt to use " +
+                        "Restricted Class: " + name;
+                    log.info(error, se);
+                    throw new ClassNotFoundException(error, se);
+                }
             }
-    
-            // (0.2) Try loading the class with the system class loader, to 
prevent
-            //       the webapp from overriding J2SE classes
+        }
+
+        boolean delegateLoad = delegate || filter(name);
+
+        // (1) Delegate to our parent if requested
+        if (delegateLoad) {
+            if (log.isDebugEnabled())
+                log.debug("  Delegating to parent classloader1 " + parent);
+            ClassLoader loader = parent;
+            if (loader == null)
+                loader = system;
             try {
-                clazz = system.loadClass(name);
+                clazz = loader.loadClass(name);
                 if (clazz != null) {
+                    if (log.isDebugEnabled())
+                        log.debug("  Loading class from parent");
                     if (resolve)
                         resolveClass(clazz);
                     return (clazz);
                 }
             } catch (ClassNotFoundException e) {
-                // Ignore
-            }
-    
-            // (0.5) Permission to access this class when using a 
SecurityManager
-            if (securityManager != null) {
-                int i = name.lastIndexOf('.');
-                if (i >= 0) {
-                    try {
-                        
securityManager.checkPackageAccess(name.substring(0,i));
-                    } catch (SecurityException se) {
-                        String error = "Security Violation, attempt to use " +
-                            "Restricted Class: " + name;
-                        log.info(error, se);
-                        throw new ClassNotFoundException(error, se);
-                    }
-                }
+                ;
             }
-    
-            boolean delegateLoad = delegate || filter(name);
-    
-            // (1) Delegate to our parent if requested
-            if (delegateLoad) {
+        }
+
+        // (2) Search local repositories
+        if (log.isDebugEnabled())
+            log.debug("  Searching local repositories");
+        try {
+            clazz = findClass(name);
+            if (clazz != null) {
                 if (log.isDebugEnabled())
-                    log.debug("  Delegating to parent classloader1 " + parent);
-                ClassLoader loader = parent;
-                if (loader == null)
-                    loader = system;
-                try {
-                    clazz = loader.loadClass(name);
-                    if (clazz != null) {
-                        if (log.isDebugEnabled())
-                            log.debug("  Loading class from parent");
-                        if (resolve)
-                            resolveClass(clazz);
-                        return (clazz);
-                    }
-                } catch (ClassNotFoundException e) {
-                    ;
-                }
+                    log.debug("  Loading class from local repository");
+                if (resolve)
+                    resolveClass(clazz);
+                return (clazz);
             }
-    
-            // (2) Search local repositories
+        } catch (ClassNotFoundException e) {
+            ;
+        }
+
+        // (3) Delegate to parent unconditionally
+        if (!delegateLoad) {
             if (log.isDebugEnabled())
-                log.debug("  Searching local repositories");
+                log.debug("  Delegating to parent classloader at end: " + 
parent);
+            ClassLoader loader = parent;
+            if (loader == null)
+                loader = system;
             try {
-                clazz = findClass(name);
+                clazz = loader.loadClass(name);
                 if (clazz != null) {
                     if (log.isDebugEnabled())
-                        log.debug("  Loading class from local repository");
+                        log.debug("  Loading class from parent");
                     if (resolve)
                         resolveClass(clazz);
                     return (clazz);
@@ -1535,30 +1554,10 @@ public class WebappClassLoader
             } catch (ClassNotFoundException e) {
                 ;
             }
-    
-            // (3) Delegate to parent unconditionally
-            if (!delegateLoad) {
-                if (log.isDebugEnabled())
-                    log.debug("  Delegating to parent classloader at end: " + 
parent);
-                ClassLoader loader = parent;
-                if (loader == null)
-                    loader = system;
-                try {
-                    clazz = loader.loadClass(name);
-                    if (clazz != null) {
-                        if (log.isDebugEnabled())
-                            log.debug("  Loading class from parent");
-                        if (resolve)
-                            resolveClass(clazz);
-                        return (clazz);
-                    }
-                } catch (ClassNotFoundException e) {
-                    ;
-                }
-            }
-    
-            throw new ClassNotFoundException(name);
         }
+
+        throw new ClassNotFoundException(name);
+
     }
 
 
@@ -2544,7 +2543,7 @@ public class WebappClassLoader
         if (clazz != null)
             return clazz;
 
-        synchronized (name.intern()) {
+        synchronized (this) {
             clazz = entry.loadedClass;
             if (clazz != null)
                 return clazz;

Modified: tomcat/tc6.0.x/trunk/java/org/apache/jasper/servlet/JasperLoader.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/jasper/servlet/JasperLoader.java?rev=941868&r1=941867&r2=941868&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/jasper/servlet/JasperLoader.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/jasper/servlet/JasperLoader.java Thu 
May  6 19:17:49 2010
@@ -91,7 +91,7 @@ public class JasperLoader extends URLCla
      *                                     
      * @exception ClassNotFoundException if the class was not found
      */                                    
-    public Class loadClass(final String name, boolean resolve)
+    public synchronized Class loadClass(final String name, boolean resolve)
         throws ClassNotFoundException {
 
         Class clazz = null;                
@@ -169,4 +169,4 @@ public class JasperLoader extends URLCla
     public final PermissionCollection getPermissions(CodeSource codeSource) {
         return permissionCollection;
     }
-}
\ No newline at end of file
+}

Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=941868&r1=941867&r2=941868&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Thu May  6 19:17:49 2010
@@ -47,6 +47,9 @@
         address via the HTTP WWW-Authenticate header when using BASIC or DIGEST
         authentication. (markt)
       </fix>
+      <fix>
+        <bug>48903</bug>: Fix deadlock in webapp class loader. (rjung)
+      </fix>
       <add>
         Include context name when reporting memory leaks to aid root cause
         identification. (markt)



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

Reply via email to