Author: tschoening
Date: Mon Feb 10 13:17:41 2014
New Revision: 1566613

URL: http://svn.apache.org/r1566613
Log:
LOGCXX-305: Property/DOMConfigurator::configureAndWatch can continue to run 
after APR termination

Added:
    incubator/log4cxx/trunk/src/test/cpp/helpers/filewatchdogtest.cpp
Modified:
    incubator/log4cxx/trunk/src/changes/changes.xml
    incubator/log4cxx/trunk/src/main/cpp/aprinitializer.cpp
    incubator/log4cxx/trunk/src/main/cpp/domconfigurator.cpp
    incubator/log4cxx/trunk/src/main/cpp/filewatchdog.cpp
    incubator/log4cxx/trunk/src/main/cpp/mutex.cpp
    incubator/log4cxx/trunk/src/main/cpp/propertyconfigurator.cpp
    incubator/log4cxx/trunk/src/main/cpp/threadspecificdata.cpp
    incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/aprinitializer.h

Modified: incubator/log4cxx/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/changes/changes.xml?rev=1566613&r1=1566612&r2=1566613&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/changes/changes.xml (original)
+++ incubator/log4cxx/trunk/src/changes/changes.xml Mon Feb 10 13:17:41 2014
@@ -53,6 +53,7 @@
                        <action issue="LOGCXX-300" type="fix">ODBCAppender 
connection settings broken (or just have changed).</action>
                        <action issue="LOGCXX-303" type="fix">DOMConfigurator 
does not set ErrorHandler.</action>
                        <action issue="LOGCXX-304" 
type="fix">BasicConfigurator::configure results in writer not set 
warning.</action>
+                       <action issue="LOGCXX-305" 
type="fix">Property/DOMConfigurator::configureAndWatch can continue to run 
after APR termination</action>
                        <action issue="LOGCXX-317" type="fix">Log4cxx triggers 
locking inversion which can result in a deadlock.</action>
                        <action issue="LOGCXX-331" 
type="fix">DailyRollingFileAppender should roll if program doesn't run at 
rolling time</action>
                        <action issue="LOGCXX-336" type="fix">Test compilation 
fails: Overloading ambiguity</action>

Modified: incubator/log4cxx/trunk/src/main/cpp/aprinitializer.cpp
URL: 
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/aprinitializer.cpp?rev=1566613&r1=1566612&r2=1566613&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/aprinitializer.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/aprinitializer.cpp Mon Feb 10 13:17:41 
2014
@@ -21,9 +21,12 @@
 #include <log4cxx/helpers/aprinitializer.h>
 #include <apr_pools.h>
 #include <apr_atomic.h>
-#include <apr_time.h>
 #include <assert.h>
 #include <log4cxx/helpers/threadspecificdata.h>
+#include <apr_thread_mutex.h>
+#include <apr_thread_proc.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/filewatchdog.h>
 
 using namespace log4cxx::helpers;
 using namespace log4cxx;
@@ -37,7 +40,7 @@ namespace {
        }
 }
 
-APRInitializer::APRInitializer() {
+APRInitializer::APRInitializer() : p(0), mutex(0), startTime(0), tlsKey(0) {
     apr_initialize();
     apr_pool_create(&p, NULL);
     apr_atomic_init(p);
@@ -45,10 +48,22 @@ APRInitializer::APRInitializer() {
 #if APR_HAS_THREADS
     apr_status_t stat = apr_threadkey_private_create(&tlsKey, tlsDestruct, p);
     assert(stat == APR_SUCCESS);
+    stat = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, p);
+    assert(stat == APR_SUCCESS);
 #endif
 }
 
 APRInitializer::~APRInitializer() {
+    {
+#if APR_HAS_THREADS
+        synchronized sync(mutex);
+#endif
+        for(std::vector<FileWatchdog*>::iterator iter = watchdogs.begin();
+            iter != watchdogs.end();
+            iter++) {
+            delete *iter;
+        }
+    }
     apr_terminate();
     isDestructed = true;
 }
@@ -71,3 +86,11 @@ apr_threadkey_t* APRInitializer::getTlsK
    return getInstance().tlsKey;
 }
 
+void APRInitializer::registerCleanup(FileWatchdog* watchdog) {
+    APRInitializer& instance(getInstance());
+#if APR_HAS_THREADS
+    synchronized sync(instance.mutex);
+#endif
+    instance.watchdogs.push_back(watchdog);
+}
+

Modified: incubator/log4cxx/trunk/src/main/cpp/domconfigurator.cpp
URL: 
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/domconfigurator.cpp?rev=1566613&r1=1566612&r2=1566613&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/domconfigurator.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/domconfigurator.cpp Mon Feb 10 
13:17:41 2014
@@ -45,6 +45,9 @@
 #include <log4cxx/helpers/charsetdecoder.h>
 #include <log4cxx/net/smtpappender.h>
 
+#define LOG4CXX 1
+#include <log4cxx/helpers/aprinitializer.h>
+
 using namespace log4cxx;
 using namespace log4cxx::xml;
 using namespace log4cxx::helpers;
@@ -812,6 +815,7 @@ void DOMConfigurator::configureAndWatch(
         File file(filename);
 #if APR_HAS_THREADS
         XMLWatchdog * xdog = new XMLWatchdog(file);
+        APRInitializer::registerCleanup(xdog);
         xdog->setDelay(delay);
         xdog->start();
 #else
@@ -825,6 +829,7 @@ void DOMConfigurator::configureAndWatch(
         File file(filename);
 #if APR_HAS_THREADS
         XMLWatchdog * xdog = new XMLWatchdog(file);
+        APRInitializer::registerCleanup(xdog);
         xdog->setDelay(delay);
         xdog->start();
 #else

Modified: incubator/log4cxx/trunk/src/main/cpp/filewatchdog.cpp
URL: 
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/filewatchdog.cpp?rev=1566613&r1=1566612&r2=1566613&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/filewatchdog.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/filewatchdog.cpp Mon Feb 10 13:17:41 
2014
@@ -22,7 +22,7 @@
 #include <apr_thread_proc.h>
 #include <apr_atomic.h>
 #include <log4cxx/helpers/transcoder.h>
-
+#include <log4cxx/helpers/exception.h>
 
 using namespace log4cxx;
 using namespace log4cxx::helpers;
@@ -39,7 +39,11 @@ warnedAlready(false), interrupted(0), th
 
 FileWatchdog::~FileWatchdog() {
    apr_atomic_set32(&interrupted, 0xFFFF);
-   thread.join();
+   try {
+        thread.interrupt();
+        thread.join();
+   } catch(Exception &e) {
+   }
 }
 
 void FileWatchdog::checkAndConfigure()
@@ -73,10 +77,10 @@ void* APR_THREAD_FUNC FileWatchdog::run(
    unsigned int interrupted = apr_atomic_read32(&pThis->interrupted);
     while(!interrupted)
    {
-      apr_sleep(APR_INT64_C(1000) * pThis->delay);
-      interrupted = apr_atomic_read32(&pThis->interrupted);
-      if (!interrupted) {
+      try {
+        Thread::sleep(pThis->delay);
         pThis->checkAndConfigure();
+      } catch(InterruptedException& ex) {
         interrupted = apr_atomic_read32(&pThis->interrupted);
       }
     }

Modified: incubator/log4cxx/trunk/src/main/cpp/mutex.cpp
URL: 
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/mutex.cpp?rev=1566613&r1=1566612&r2=1566613&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/mutex.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/mutex.cpp Mon Feb 10 13:17:41 2014
@@ -19,6 +19,7 @@
 #include <log4cxx/helpers/mutex.h>
 #include <log4cxx/helpers/exception.h>
 #include <apr_thread_mutex.h>
+#include <log4cxx/helpers/pool.h>
 #include <assert.h>
 #if !defined(LOG4CXX)
 #define LOG4CXX 1

Modified: incubator/log4cxx/trunk/src/main/cpp/propertyconfigurator.cpp
URL: 
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/propertyconfigurator.cpp?rev=1566613&r1=1566612&r2=1566613&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/propertyconfigurator.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/propertyconfigurator.cpp Mon Feb 10 
13:17:41 2014
@@ -39,6 +39,9 @@
 #include <log4cxx/helpers/transcoder.h>
 #include <log4cxx/helpers/fileinputstream.h>
 
+#define LOG4CXX 1
+#include <log4cxx/helpers/aprinitializer.h>
+
 
 using namespace log4cxx;
 using namespace log4cxx::spi;
@@ -135,6 +138,7 @@ void PropertyConfigurator::configureAndW
         const File& configFilename, long delay)
 {
     PropertyWatchdog * pdog = new PropertyWatchdog(configFilename);
+    APRInitializer::registerCleanup(pdog);
     pdog->setDelay(delay);
     pdog->start();
 }

Modified: incubator/log4cxx/trunk/src/main/cpp/threadspecificdata.cpp
URL: 
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/threadspecificdata.cpp?rev=1566613&r1=1566612&r2=1566613&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/threadspecificdata.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/threadspecificdata.cpp Mon Feb 10 
13:17:41 2014
@@ -18,6 +18,7 @@
 #include <log4cxx/logstring.h>
 #include <log4cxx/helpers/threadspecificdata.h>
 #include <log4cxx/helpers/exception.h>
+#include <apr_thread_proc.h>
 #if !defined(LOG4CXX)
 #define LOG4CXX 1
 #endif

Modified: 
incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/aprinitializer.h
URL: 
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/aprinitializer.h?rev=1566613&r1=1566612&r2=1566613&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/aprinitializer.h 
(original)
+++ incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/aprinitializer.h 
Mon Feb 10 13:17:41 2014
@@ -22,28 +22,44 @@
 #error "aprinitializer.h should only be included by log4cxx implementation"
 #endif
 
-#include <log4cxx/helpers/pool.h>
-#include <apr_pools.h>
-#include <apr_thread_proc.h>
+#include <vector>
+
+extern "C" {
+typedef struct apr_thread_mutex_t apr_thread_mutex_t;
+typedef struct apr_threadkey_t apr_threadkey_t;
+}
+
+#include <apr_time.h>
 
 namespace log4cxx
 {
   namespace helpers
   {
+    class FileWatchdog;
+    
     class APRInitializer
     {
     public:
-    static log4cxx_time_t initialize();
+    static apr_time_t initialize();
     static apr_pool_t* getRootPool();
     static apr_threadkey_t* getTlsKey();
     static bool isDestructed;
+    
+    /**
+     *  Register a FileWatchdog for deletion prior to
+     *    APR termination.  FileWatchdog must be 
+     *    allocated on heap and not deleted elsewhere.
+     */
+    static void registerCleanup(FileWatchdog* watchdog);
 
     private:
       APRInitializer();
       APRInitializer(const APRInitializer&);
       APRInitializer& operator=(const APRInitializer&);
       apr_pool_t* p;
-      log4cxx_time_t startTime;
+      apr_thread_mutex_t* mutex;
+      std::vector<FileWatchdog*> watchdogs; 
+      apr_time_t startTime;
       apr_threadkey_t* tlsKey;
       static APRInitializer& getInstance();
 

Added: incubator/log4cxx/trunk/src/test/cpp/helpers/filewatchdogtest.cpp
URL: 
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/test/cpp/helpers/filewatchdogtest.cpp?rev=1566613&view=auto
==============================================================================
--- incubator/log4cxx/trunk/src/test/cpp/helpers/filewatchdogtest.cpp (added)
+++ incubator/log4cxx/trunk/src/test/cpp/helpers/filewatchdogtest.cpp Mon Feb 
10 13:17:41 2014
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/filewatchdog.h>
+#include "../logunit.h"
+#include "apr_time.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+/**
+ *
+ * FileWatchdog tests.
+ */
+LOGUNIT_CLASS(FileWatchdogTest) {
+  LOGUNIT_TEST_SUITE(FileWatchdogTest);
+          LOGUNIT_TEST(testShutdownDelay);
+  LOGUNIT_TEST_SUITE_END();
+  
+private:
+    class MockWatchdog : public FileWatchdog {
+    public:
+        MockWatchdog(const File& file) : FileWatchdog(file) {
+        }
+        
+        void doOnChange() {
+        }
+    };
+    
+public:
+  
+  /**
+   *  Tests that FileWatchdog will respond to a shutdown request more rapidly
+   *     than waiting out its delay. 
+   */
+  void testShutdownDelay() {
+      apr_time_t start = apr_time_now();
+      {
+        MockWatchdog dog(File(LOG4CXX_STR("input/patternlayout1.properties")));
+        dog.start();
+        //   wait 50 ms for thread to get rolling 
+        apr_sleep(50000);
+      }
+      apr_time_t delta = apr_time_now() - start;
+      LOGUNIT_ASSERT(delta < 30000000);
+  }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(FileWatchdogTest);
+


Reply via email to