Utils/Daemon: Add instance() and logReopen() member and bind SIGHUP to logReopen()
g0dil [Fri, 4 Apr 2008 11:59:14 +0000 (11:59 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@783 270642c3-0616-0410-b53a-bc976706d245

Utils/Daemon/Daemon.cc
Utils/Daemon/Daemon.hh
Utils/Daemon/Daemon.test.cc

index fe55821..079b383 100644 (file)
@@ -123,6 +123,35 @@ prefix_ void senf::Daemon::openLog()
     }
 }
 
+prefix_ void senf::Daemon::logReopen()
+{
+    if (! stdoutLog_.empty()) {
+        int fd (::open(stdoutLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666));
+        if (fd < 0) 
+            goto error;
+        if (::dup2(fd, 1) < 0) 
+            goto error;
+        if (stderrLog_ == stdoutLog_) {
+            if (::dup2(fd, 2) < 0) 
+                goto error;
+            return;
+        }
+    }
+    if (! stderrLog_.empty()) {
+        int fd (::open(stderrLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666));
+        if (fd < 0) 
+            goto error;
+        if (::dup2(fd, 2) < 0) 
+            goto error;
+    }
+    return;
+
+ error:
+    SENF_LOG(
+        (senf::log::CRITICAL)
+        ("log-file reopen failed: (" << errno << ") " << ::strerror(errno)) );
+}
+
 prefix_ void senf::Daemon::pidFile(std::string const & f)
 {
     pidfile_ = f;
@@ -234,13 +263,24 @@ prefix_ int senf::Daemon::start(int argc, char ** argv)
     return 0;
 }
 
+prefix_ senf::Daemon & senf::Daemon::instance()
+{
+    BOOST_ASSERT( instance_ );
+    return *instance_;
+}
+
 ////////////////////////////////////////
 // protected members
 
 prefix_ senf::Daemon::Daemon()
     : argc_(0), argv_(0), daemonize_(true), stdout_(-1), stderr_(-1), pidfile_(""),
       pidfileCreated_(false), detached_(false)
-{}
+{
+    BOOST_ASSERT( ! instance_ );
+    instance_ = this;
+}
+
+senf::Daemon * senf::Daemon::instance_ (0);
 
 ////////////////////////////////////////
 // private members
@@ -466,12 +506,25 @@ namespace {
 
 #endif
 
+namespace {
+    void sighupHandler(int sig)
+    {
+        senf::Daemon::instance().logReopen();
+    }
+}
+
 prefix_ void senf::Daemon::installSighandlers()
 {
-#ifdef SENF_DEBUG
     struct ::sigaction sa;
-    sa.sa_sigaction = &fatalSignalsHandler;
+
     ::sigemptyset(&sa.sa_mask);
+    sa.sa_handler = &sighupHandler;
+    sa.sa_flags = SA_RESTART;
+
+    ::sigaction(SIGHUP,   &sa, NULL);
+
+#ifdef SENF_DEBUG
+    sa.sa_sigaction = &fatalSignalsHandler;
     sa.sa_flags = SA_RESTART | SA_SIGINFO;
 
     ::sigaction(SIGILL,    &sa, NULL);
index d0ba4a7..76e10e7 100644 (file)
@@ -28,6 +28,7 @@
 
 // Custom includes
 #include <boost/utility.hpp>
+#include "../Logger/SenfLog.hh"
 
 //#include "Daemon.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
@@ -103,6 +104,8 @@ namespace senf {
     class Daemon : boost::noncopyable
     {
     public:
+        SENF_LOG_CLASS_AREA();
+
         ///////////////////////////////////////////////////////////////////////////
         // Types
         
@@ -158,12 +161,18 @@ namespace senf {
 
         static void exit(unsigned code=0); ///< Terminate daemon with failure
 
+        void logReopen();               ///< Reopen the log files
+                                        /**< This is used when rotating the logs. By default,
+                                             SIGHUP calls logReopen. */
+
         ///\}
         
         int start(int argc, char ** argv); ///< Called from main() to launch daemon.
                                         /**< Normally not called directly but from the
                                              \ref SENF_DAEMON_MAIN macro. */
 
+        static Daemon & instance();     ///< Return the Daemon instance
+
     protected:
         Daemon();
 
@@ -212,6 +221,8 @@ namespace senf {
         bool pidfileCreated_;
 
         bool detached_;
+
+        static Daemon * instance_;
     };
 
     /** \brief Provide \c main() function
index f6c8bf6..f561e97 100644 (file)
@@ -77,9 +77,11 @@ namespace {
         return instance.start(argc, argv);
     }
 
+    int pid;
+
     int run(int argc, char ** argv)
     {
-        int pid (::fork());
+        pid  = ::fork();
         if (pid < 0) throw senf::SystemException("::fork()");
         if (pid == 0) {
             ::_exit(myMain(argc, argv));
@@ -100,16 +102,29 @@ BOOST_AUTO_UNIT_TEST(testDaemon)
 
     BOOST_CHECK( ! boost::filesystem::exists("invalid.log") );
     BOOST_CHECK( ! boost::filesystem::exists("invalid.pid") );
-    BOOST_CHECK( boost::filesystem::exists("testDaemon.pid") );
+    BOOST_REQUIRE( boost::filesystem::exists("testDaemon.pid") );
+    BOOST_REQUIRE( boost::filesystem::exists("testDaemon.log") );
+    
+    boost::filesystem::rename("testDaemon.log", "testDaemon.log.1");
+    {
+        std::ifstream pidFile ("testDaemon.pid");
+        int pid (0);
+        BOOST_REQUIRE( pidFile >> pid );
+        BOOST_REQUIRE( pid != 0 );
+        ::kill(pid, SIGHUP);
+    }
+
     delay(1000);
     BOOST_CHECK( ! boost::filesystem::exists("testDaemon.pid") );
-    BOOST_REQUIRE( boost::filesystem::exists("testDaemon.log") );
+    BOOST_CHECK( boost::filesystem::exists("testDaemon.log") );
+    BOOST_REQUIRE( boost::filesystem::exists("testDaemon.log.1") );
     
-    std::ifstream log ("testDaemon.log");
+    std::ifstream log ("testDaemon.log.1");
     std::stringstream data;
     data << log.rdbuf();
     BOOST_CHECK_EQUAL( data.str(), "Running init()\nRunning run()\n" );
     BOOST_CHECK_NO_THROW( boost::filesystem::remove("testDaemon.log") );
+    BOOST_CHECK_NO_THROW( boost::filesystem::remove("testDaemon.log.1") );
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////