Packets/DefaultBundle: Document finalize() action
[senf.git] / Utils / DaemonTools.hh
1 // $Id$
2 //
3 // Copyright (C) 2006 Stefan Bund <g0dil@senf.berlios.de>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the
17 // Free Software Foundation, Inc.,
18 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 /** \file
21     \brief DaemonTools public header */
22
23 /** \defgroup process Process Management
24
25     Future features:
26
27     \li Daemon manager watching the real daemon. Auto-restart, when the daemon fails
28
29     \li Provide access to the config console indirectly via the daemon manager. This allows to
30         connect to the daemon manager console even if the app is not running
31     
32     \li For this to be efficient, the daemon manager must be it's own executable (e.g. senf-launch)
33
34     \li auto-detect whether called from senf-launch or not
35
36     \li when daemon is running, the console is transparently forwarded to the daemon. The daemon
37         however can still access the daemon manager as a subgroup
38     
39     \li No idea, whether this is sensible: Make the daemon manager completely self-contained (not
40         dependent on any external OS support) by providing our own log-file rotation support.
41
42     This collection of utilities provides help in managing daemon processes.
43
44     \idea A closeall()/closemost() function which is useful when starting child processes. We'll use
45         getrlimit to now the biggest filehandle and close all of em. closemost() takes a number of
46         file handles as arg and will keep those open.
47
48     \idea We might want to add other oft used utitlities: chroot(), setreuid(), pipes() / IPC ...
49  */
50
51 #ifndef HH_DaemonTools_
52 #define HH_DaemonTools_ 1
53
54 // Custom includes
55 #include <string>
56 #include <boost/utility.hpp>
57
58 //#include "DaemonTools.mpp"
59 ///////////////////////////////hh.p////////////////////////////////////////
60
61 namespace senf {
62
63     /** \brief Daemon process
64
65         This class provides the infrastructure to implement robust daemon processes. A daemon
66         process is implemented by deriving from senf::Daemon and implementing the necessary
67         (virtual) member functions.
68         \code
69         class MyDaemon : public senf::Daemon
70         {
71             void configure() {
72                 // Set configuration parameters like daemonize(), pidFile() etc.
73             }
74
75             void init() {
76                 // Initialize application. Setup all necessary objects. After init()
77                 // has completed, is startup should not fail anymore
78             }
79
80             void run() {
81                 // Main application code should be called here.
82             }
83         };
84         \endcode
85
86         The startup procedure is divided into three steps:
87         \li First, configure() is called. configure() should be as simple as possible. It just needs
88             to set the daemon parameters. No further setup should be done here.
89         \li init() is called after fork() but while still connected to the terminal. init() should
90             do all necessary application setup. Here, all configuration or user errors should be
91             detected and properly diagnosed.
92         \li After init() returns, the application will detach from the terminal. Now run() is called
93             to enter the application main loop.
94
95         Since there are times, where separating init() and run() into two separate functions is
96         difficult, instead of defining init() and run(), the member main() may be defined. This
97         member must call detach() as soon as initialization is completed to detach from the
98         foreground terminal.
99
100         
101         
102         \ingroup process
103       */
104     class Daemon : boost::noncopyable
105     {
106     public:
107         ///////////////////////////////////////////////////////////////////////////
108         // Types
109         
110         /// Select standard stream to redirect
111         enum StdStream { 
112             StdOut /** Standard output stream */
113         ,   StdErr /** Standard error stream */
114         ,    Both  /** Both, standard output and error stream */
115         }; 
116
117         ///////////////////////////////////////////////////////////////////////////
118         ///\name Structors and default members
119         ///\{
120
121         virtual ~Daemon();
122
123         ///\}
124         ///\name Parameters
125         ///\{
126
127         void daemonize(bool);           ///< Configure whether to run in fore- or background
128         bool daemon();                  ///< \c true, if running as daemon
129
130         void consoleLog(std::string, StdStream which = Both); ///< Configure console log file
131                                         /**< May be called multiple times to set the log file
132                                              for stdout and stderr seperately. Any standard stream
133                                              not assigned to a log file will be redirected to
134                                              <tt>/dev/null</tt>. 
135
136                                              When running in the foreground, the log files will be
137                                              ignored. */
138
139         void pidFile(std::string, bool unique = true); ///< Configure pid file
140
141         ///\}
142         ///\name Auxiliary helpers
143         ///\{
144
145         void detach();                  ///< Detach into background now
146                                         /**< This is \e not the same as forking. The process will
147                                              already have forked into the background but until
148                                              detach() is called (either automatically after init()
149                                              returns or manually), the front end (foreground)
150                                              process will wait for the background process to ensure
151                                              successful startup. */
152
153         int argc();                     ///< Access command line parameter count
154         char const ** argv();           ///< Access command line parameters
155
156         void fail(int code=1);          ///< Terminate startup with failure
157
158         ///\}
159         
160         int start(int argc, char const ** argv); ///< Called from main() to launch daemon.
161                                         /**< Normally not called directly but from the
162                                              \ref SENF_DAEMON_MAIN macro. */
163
164     protected:
165         Daemon();
166
167 #   ifdef DOXYGEN
168     protected:
169 #   else
170     private:
171 #   endif
172
173         virtual void configure();       ///< Called before forking to configure the daemon class
174         virtual void main();            ///< Called after forking to execute the main application
175                                         /**< The default implementation will call init(), detach()
176                                              and then run(). It is preferred to override init() and
177                                              run() if possible. */
178         virtual void init();            ///< Called to initialize the main application
179                                         /**< While init() is running, the application still is
180                                              connected to the controlling terminal. Error messages
181                                              will be shown to the user.
182
183                                              This member is only called, if the default main()
184                                              implementation is not overridden. */
185         virtual void run();             ///< Called to execute main application
186                                         /**< Called after detaching from the controlling
187                                              terminal.
188
189                                              This member is only called, if the default main()
190                                              implementation is not overridden. */
191     private:
192
193         void pidfileCreate();
194
195         int argc_;
196         char const ** argv_;
197
198         bool daemonize_;
199         int stdout_;
200         int stderr_;
201         std::string pidfile_;
202         bool unique_;
203
204         bool detached_;
205     };
206
207     /** \brief Provide \c main() function
208
209         This macro will provide a \c main() function to launch the daemon process defined in \a
210         klass. \a klass must be a class derived from senf::Daemon.
211
212         \ingroup process
213      */
214 #   define SENF_DAEMON_MAIN(klass)                                                                \
215         int main(int argc, char const ** argv)                                                    \
216         {                                                                                         \
217             klass instance;                                                                       \
218             return instance.start(argc, argv);                                                    \
219         }
220
221     /// \addtogroup process
222     /// @{
223
224     void daemonize();                   ///< Make the current process a daemon process
225                                         /**< daemonize() will fork, detach from the controlling
226                                              terminal and start a new process group. */
227     void redirect_stdio(std::string const & path = "/dev/null"); ///< Redirect STDIN, STDOUT and STDERR
228                                         /**< All standard file-descriptors will be redirected to the
229                                              given path defaulting to <tt>/dev/null</tt>
230                                              \param[in] path path to redirect to */
231
232     /// @}
233 }
234
235 ///////////////////////////////hh.e////////////////////////////////////////
236 //#include "DaemonTools.cci"
237 //#include "DaemonTools.ct"
238 //#include "DaemonTools.cti"
239 //#include "DaemonTools.mpp"
240 #endif
241
242 \f
243 // Local Variables:
244 // mode: c++
245 // fill-column: 100
246 // c-file-style: "senf"
247 // indent-tabs-mode: nil
248 // ispell-local-dictionary: "american"
249 // compile-command: "scons -u test"
250 // comment-column: 40
251 // End: