Author: markt
Date: Wed Mar  3 17:26:54 2010
New Revision: 918594

URL: http://svn.apache.org/viewvc?rev=918594&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=48831
Address issues 1 & 2 by using a ReadWriteLock to control access to the writer. 
This ensures messages won't be written while the writer is null. Note there is 
no (easy) way to not close the handler.
Address issue 3 by re-enabling the JULI shutdown hook if JULI is being used and 
Tomcat isn't stopped via a shutdown hook.
Address issue 4 by making ClassLoaderLogManager#useShutdownHook volatile

Modified:
    tomcat/trunk/java/org/apache/catalina/startup/Catalina.java
    tomcat/trunk/java/org/apache/juli/ClassLoaderLogManager.java
    tomcat/trunk/java/org/apache/juli/FileHandler.java

Modified: tomcat/trunk/java/org/apache/catalina/startup/Catalina.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/Catalina.java?rev=918594&r1=918593&r2=918594&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/Catalina.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/Catalina.java Wed Mar  3 
17:26:54 2010
@@ -607,6 +607,14 @@
             // doesn't get invoked twice
             if (useShutdownHook) {
                 Runtime.getRuntime().removeShutdownHook(shutdownHook);
+
+                // If JULI is being used, re-enable JULI's shutdown to ensure
+                // log messages are not lost
+                LogManager logManager = LogManager.getLogManager();
+                if (logManager instanceof ClassLoaderLogManager) {
+                    ((ClassLoaderLogManager) logManager).setUseShutdownHook(
+                            true);
+                }
             }
         } catch (Throwable t) {
             // This will fail on JDK 1.2. Ignoring, as Tomcat can run

Modified: tomcat/trunk/java/org/apache/juli/ClassLoaderLogManager.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/juli/ClassLoaderLogManager.java?rev=918594&r1=918593&r2=918594&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/juli/ClassLoaderLogManager.java (original)
+++ tomcat/trunk/java/org/apache/juli/ClassLoaderLogManager.java Wed Mar  3 
17:26:54 2010
@@ -93,9 +93,9 @@
      * Determines if the shutdown hook is used to perform any necessary
      * clean-up such as flushing buffered handlers on JVM shutdown. Defaults to
      * <code>true</code> but may be set to false if another component ensures
-     * that 
+     * that {...@link #shutdown()} is called.
      */
-    protected boolean useShutdownHook = true;
+    protected volatile boolean useShutdownHook = true;
 
     
     // ------------------------------------------------------------- Properties

Modified: tomcat/trunk/java/org/apache/juli/FileHandler.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/juli/FileHandler.java?rev=918594&r1=918593&r2=918594&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/juli/FileHandler.java (original)
+++ tomcat/trunk/java/org/apache/juli/FileHandler.java Wed Mar  3 17:26:54 2010
@@ -26,6 +26,8 @@
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
 import java.sql.Timestamp;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.logging.ErrorManager;
 import java.util.logging.Filter;
 import java.util.logging.Formatter;
@@ -96,9 +98,16 @@
      * The PrintWriter to which we are currently logging, if any.
      */
     private volatile PrintWriter writer = null;
-    
+
+
+    /**
+     * Lock used to control access to the writer.
+     */
+    protected ReadWriteLock writerLock = new ReentrantReadWriteLock();
+
+
     /**
-     * Log buffer size
+     * Log buffer size.
      */
     private int bufferSize = -1;
 
@@ -123,15 +132,22 @@
         String tsString = ts.toString().substring(0, 19);
         String tsDate = tsString.substring(0, 10);
 
+        writerLock.readLock().lock();
         // If the date has changed, switch log files
         if (!date.equals(tsDate)) {
-            synchronized (this) {
-                if (!date.equals(tsDate)) {
-                    closeWriter();
-                    date = tsDate;
-                    openWriter();
-                }
-            }
+               // Update to writeLock before we switch
+            writerLock.readLock().unlock();
+               writerLock.writeLock().lock();
+               // Make sure another thread hasn't already done this
+               if (!date.equals(tsDate)) {
+                   closeWriter();
+                   date = tsDate;
+                   openWriter();
+               }
+            // Down grade to read-lock. This ensures the writer remains valid
+            // until the log message is written
+            writerLock.readLock().lock();
+            writerLock.writeLock().unlock();
         }
 
         String result = null;
@@ -139,11 +155,11 @@
             result = getFormatter().format(record);
         } catch (Exception e) {
             reportError(null, e, ErrorManager.FORMAT_FAILURE);
+               writerLock.readLock().unlock();
             return;
         }
         
         try {
-            PrintWriter writer = this.writer;
             if (writer!=null) {
                 writer.write(result);
                 if (bufferSize < 0) {
@@ -155,8 +171,9 @@
         } catch (Exception e) {
             reportError(null, e, ErrorManager.WRITE_FAILURE);
             return;
+        } finally {
+               writerLock.readLock().unlock();
         }
-        
     }
     
     
@@ -174,8 +191,7 @@
     protected void closeWriter() {
         
         try {
-            PrintWriter writer = this.writer;
-            this.writer = null;
+            writerLock.writeLock().lock();
             if (writer == null)
                 return;
             writer.write(getFormatter().getTail(this));
@@ -185,8 +201,9 @@
             date = "";
         } catch (Exception e) {
             reportError(null, e, ErrorManager.CLOSE_FAILURE);
+        } finally {
+            writerLock.writeLock().unlock();
         }
-        
     }
 
 
@@ -197,12 +214,14 @@
     public void flush() {
 
         try {
-            PrintWriter writer = this.writer;
-            if (writer==null)
+               writerLock.readLock().lock();
+            if (writer == null)
                 return;
             writer.flush();
         } catch (Exception e) {
             reportError(null, e, ErrorManager.FLUSH_FAILURE);
+        } finally {
+               writerLock.readLock().unlock();
         }
         
     }
@@ -306,6 +325,7 @@
             String encoding = getEncoding();
             FileOutputStream fos = new FileOutputStream(pathname, true);
             OutputStream os = bufferSize>0?new 
BufferedOutputStream(fos,bufferSize):fos;
+            writerLock.writeLock().lock();
             writer = new PrintWriter(
                     (encoding != null) ? new OutputStreamWriter(os, encoding)
                                        : new OutputStreamWriter(os), false);
@@ -313,6 +333,8 @@
         } catch (Exception e) {
             reportError(null, e, ErrorManager.OPEN_FAILURE);
             writer = null;
+        } finally {
+            writerLock.writeLock().unlock();
         }
 
     }



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

Reply via email to