X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Utils%2FDaemon%2FDaemon.hh;h=f0d3e6b50c8fc86b0ce2da51210fc54d0c3015c0;hb=82e8df5de8b11448423388632e8602ad97bc7885;hp=3526cb3f760d698807b07d2ffba9c96e343af468;hpb=9e69297ff7a7bcd9d952a38e35bbf124cb7f1dda;p=senf.git diff --git a/Utils/Daemon/Daemon.hh b/Utils/Daemon/Daemon.hh index 3526cb3..f0d3e6b 100644 --- a/Utils/Daemon/Daemon.hh +++ b/Utils/Daemon/Daemon.hh @@ -1,8 +1,8 @@ // $Id$ // -// Copyright (C) 2007 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer NETwork research (NET) +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -23,57 +23,88 @@ /** \file \brief Daemon public header */ -#ifndef HH_Daemon_ -#define HH_Daemon_ 1 +#ifndef HH_SENF_Utils_Daemon_Daemon_ +#define HH_SENF_Utils_Daemon_Daemon_ 1 // Custom includes #include +#include "../Logger/SenfLog.hh" //#include "Daemon.mpp" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { - /** \brief Daemon process - - This class provides the infrastructure to implement robust daemon processes. A daemon - process is implemented by deriving from senf::Daemon and implementing the necessary - (virtual) member functions. - \code - class MyDaemon : public senf::Daemon - { - void configure() { - // Set configuration parameters like daemonize(), pidFile() etc. - } - - void init() { - // Initialize application. Setup all necessary objects. After init() - // has completed, is startup should not fail anymore - } - - void run() { - // Main application code should be called here. - } - }; - \endcode - - The startup procedure is divided into three steps: - \li First, configure() is called. configure() should be as simple as possible. It just needs - to set the daemon parameters. No further setup should be done here. - \li init() is called after fork() but while still connected to the terminal. init() should - do all necessary application setup. Here, all configuration or user errors should be - detected and properly diagnosed. - \li After init() returns, the application will detach from the terminal. Now run() is called - to enter the application main loop. - - Since there are times, where separating init() and run() into two separate functions is - difficult, instead of defining init() and run(), the member main() may be defined. This - member must call detach() as soon as initialization is completed to detach from the - foreground terminal. + /** \brief %Daemon process + + The %Daemon class provides simple management for daemon processes. Specifically, it implements + \li Safe startup. If the startup fails, the foreground process which launches the + daemon will terminate with an appropriate error exit code. + \li Straight forward application initialization. The daemon process is forked before + even initializing the application. The initialization procedure must not cater for a + later fork(). + \li Automatic pid file management. The daemon will not be started, if a valid pid file is + found. Stale pid files are automatically removed. + \li Console log management. It is possible, to redirect standard output and error to + one or two log files. Messages pertaining to application initialization will be written + to both the console and the log file whereas later messages will be directed to the log + file only. + \li Optional foreground execution. The daemon may be started in the foreground for + debugging purposes. In this case, the console log file(s) is/are automatically + suppressed. + + Starting the daemon process proceeds along the following steps: + \li The daemon is started by calling the daemon class instances start() member. This + normally happens from the \c main() function generated by \ref SENF_DAEMON_MAIN(). + \li configure() is called. This (virtual) member configures the daemon manager by calling + the Daemon class parameter members. + \li The log files are opened, \c fork() is called and the pid file is checked and + created. The parent (foreground) process keeps running overseeing the daemon process. + \li main() is called. This virtual member may optionally be overridden in the derived + class. Here we assume, main() is not overridden so the default implementation is used. + \li main() calls init(). + \li after init() returns, main() calls detach(). + \li detach() signals successful startup to the parent process. The parent process terminates + leaving the daemon process running in the background. + \li main() calls run() + \li If run() ever returns, the daemon process terminates. + \li Whenever the process terminates normally (not necessarily successfully), the pid file is + automatically removed. + + The parameter members are used from configure() to configure the daemon manager. See below + for details. The \e default configure() implementation will scan the command line arguments + to check for the following parameters: + + + + + + + + + +
--no-daemonRun in foreground
--console-log=stdout[,stderr]Set the + console log file(s). If only \a stdout is specified (with no comma), the same log file + configuration will be applied to the standard output and error stream. Otherwise each stream + is assigned it's own log file. If either log file name is empty, the command will not change + the log file of that stream, the default log file will be used. If the log file name is set + to 'none', the log file will be disabled.
--pid-file=pidfileSet pid file path
+ + The default configure() implementation will use whatever parameters have been set beforehand + as default values. These default values should be set in a derived class configure() + implementation. After setting the default values, the configure() implementation may choose + to call this default configure() implementation to scan for command line parmeters. The + default configure() implementation does \e not completely parse the command line + arguments. It just checks, if any of above arguments are present and precesses them. Other + arguments are completely ignored. The command line parameters should be completely processed + within init(). + */ class Daemon : boost::noncopyable { public: + SENF_LOG_CLASS_AREA(); + /////////////////////////////////////////////////////////////////////////// // Types @@ -108,6 +139,9 @@ namespace senf { ignored. */ void pidFile(std::string const &); ///< Configure pid file + /**< If a pid file is configured it will be checked on + daemon startup. If another running instance of the + daemon is detected, starting the daemon will fail. */ ///\} ///\name Auxiliary helpers @@ -123,8 +157,13 @@ namespace senf { int argc(); ///< Access command line parameter count char const ** argv(); ///< Access command line parameters + void removeDaemonArgs(); ///< Remove the daemon arguments from argc()/argv() + + static void exit(unsigned code=0); ///< Terminate daemon with failure - void fail(int code=1); ///< Terminate startup with failure + void logReopen(); ///< Reopen the log files + /**< This is used when rotating the logs. By default, + SIGHUP calls logReopen. */ ///\} @@ -132,10 +171,14 @@ namespace senf { /**< Normally not called directly but from the \ref SENF_DAEMON_MAIN macro. */ + static Daemon & instance(); ///< Return the Daemon instance + protected: Daemon(); virtual void configure(); ///< Called before forking to configure the daemon class + /**< This default implementation will parser some command + line parameters. See the class documentation above. */ # ifdef DOXYGEN protected: @@ -161,10 +204,10 @@ namespace senf { This member is only called, if the default main() implementation is not overridden. */ private: - void openLog(); void fork(); bool pidfileCreate(); + void installSighandlers(); int argc_; char const ** argv_; @@ -175,8 +218,11 @@ namespace senf { int stdout_; int stderr_; std::string pidfile_; + bool pidfileCreated_; bool detached_; + + static Daemon * instance_; }; /** \brief Provide \c main() function @@ -196,7 +242,7 @@ namespace senf { } ///////////////////////////////hh.e//////////////////////////////////////// -//#include "Daemon.cci" +#include "Daemon.cci" //#include "Daemon.ct" //#include "Daemon.cti" #endif