From: g0dil Date: Fri, 4 Apr 2008 11:59:14 +0000 (+0000) Subject: Utils/Daemon: Add instance() and logReopen() member and bind SIGHUP to logReopen() X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=b7f7003f523fa8251ac44b969374c7385d053cc4;p=senf.git Utils/Daemon: Add instance() and logReopen() member and bind SIGHUP to logReopen() git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@783 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Utils/Daemon/Daemon.cc b/Utils/Daemon/Daemon.cc index fe55821..079b383 100644 --- a/Utils/Daemon/Daemon.cc +++ b/Utils/Daemon/Daemon.cc @@ -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); diff --git a/Utils/Daemon/Daemon.hh b/Utils/Daemon/Daemon.hh index d0ba4a7..76e10e7 100644 --- a/Utils/Daemon/Daemon.hh +++ b/Utils/Daemon/Daemon.hh @@ -28,6 +28,7 @@ // Custom includes #include +#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 diff --git a/Utils/Daemon/Daemon.test.cc b/Utils/Daemon/Daemon.test.cc index f6c8bf6..f561e97 100644 --- a/Utils/Daemon/Daemon.test.cc +++ b/Utils/Daemon/Daemon.test.cc @@ -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////////////////////////////////////////