12 #include "wvlinklist.h"
16 #include "wvcrashlog.h"
18 #include "wvatomicfile.h"
21 #include <sys/types.h>
29 # define CAN_SYSLOG true
30 # define CAN_DAEMONIZE true
32 # define CAN_SYSLOG false
33 # define CAN_DAEMONIZE false
37 static const int STDOUT_FILENO = 0;
41 WvDaemon *WvDaemon::singleton = NULL;
46 static void sighup_handler(
int signum)
48 signal(signum, SIG_IGN);
50 WvDaemon::me()->
log(WvLog::Notice,
"Restarting on signal %s.\n", signum);
55 static void sigterm_handler(
int signum)
57 signal(signum, SIG_DFL);
59 WvDaemon::me()->
log(WvLog::Notice,
"Dying on signal %s.\n", signum);
60 WvDaemon::me()->
die();
64 static void sigquit_handler(
int signum)
66 signal(signum, SIG_IGN);
75 WvDaemonCallback _start_callback,
76 WvDaemonCallback _run_callback,
77 WvDaemonCallback _stop_callback)
83 log_level = WvLog::Info;
85 start_callback = _start_callback;
86 run_callback = _run_callback;
87 stop_callback = _stop_callback;
89 assert(singleton == NULL);
93 "Decrease log level (can be used multiple times)",
94 wv::bind(&WvDaemon::dec_log_level,
this, _1));
96 "Increase log level (can be used multiple times)",
97 wv::bind(&WvDaemon::inc_log_level,
this, _1));
100 "Fork into background and return (implies --syslog)",
101 wv::bind(&WvDaemon::set_daemonize,
this, _1));
105 "Write log entries to syslog", syslog);
107 "Do not write log entries to syslog", syslog);
114 WvDaemon::~WvDaemon()
124 pid_t pid = ::fork();
127 wverr->print(
"Failed to fork daemon: %s\n",
137 wverr->print(
"Failed to double-fork daemon: %s\n",
151 null_fd = ::open(
"/dev/null", O_RDWR);
154 log(WvLog::Error,
"Failed to open /dev/null: %s\n",
158 }
while (null_fd == 0 || null_fd == 1 || null_fd == 2);
160 if (::dup2(null_fd, 0) == -1
161 || ::dup2(null_fd, 1) == -1
162 || ::dup2(null_fd, 2) == -1)
164 log(WvLog::Error,
"Failed to dup2(null_fd, (0|1|2)): %s\n",
173 if (::fcntl(0, F_SETFD, 0) == -1
174 || ::fcntl(1, F_SETFD, 0) == -1
175 || ::fcntl(2, F_SETFD, 0) == -1)
177 log(WvLog::Warning,
"Failed to fcntl((0|1|2), F_SETFD, 0): %s\n",
193 if (CAN_SYSLOG && syslog)
212 int WvDaemon::_run(
const char *argv0)
217 wvcrash_setup(argv0, version);
220 if (CAN_SYSLOG && syslog)
223 _want_to_die =
false;
227 _want_to_restart =
false;
245 void WvDaemon::do_load()
254 if (old_pid_fd.isok())
256 WvString line = old_pid_fd.getline(0);
259 pid_t old_pid = line.
num();
260 if (old_pid > 0 && (kill(old_pid, 0) == 0 || errno == EPERM))
263 "%s is already running (pid %s); exiting\n",
275 pid_fd.print(
"%s\n", getpid());
277 log(WvLog::Warning,
"Failed to write PID file %s: %s\n",
282 log(WvLog::Notice,
"Starting %s version %s.\n",
name, version);
286 signal(SIGINT, SIG_IGN);
288 signal(SIGINT, sigterm_handler);
289 signal(SIGTERM, sigterm_handler);
290 signal(SIGQUIT, sigquit_handler);
291 signal(SIGHUP, sighup_handler);
299 void WvDaemon::do_start()
306 void WvDaemon::do_run()
313 void WvDaemon::do_stop()
320 void WvDaemon::do_unload()
326 signal(SIGHUP, SIG_DFL);
327 signal(SIGQUIT, SIG_DFL);
328 signal(SIGINT, SIG_DFL);
329 signal(SIGTERM, SIG_DFL);
332 log(WvLog::Notice,
"Exiting with status %s\n", _exit_status);
341 bool WvDaemon::set_daemonize(
void *)
Captures formatted log messages and outputs them to the specified file descriptor.
void set_version(WvStringParm version)
Set the –version string.
void add_option(char short_option, WvStringParm long_option, WvStringParm desc, WvStringParm arg_desc, int &val)
Add a switch that takes an integer argument.
WvArgs args
The arguments the daemon accepts; the defaults are described above.
void add_set_bool_option(char short_option, WvStringParm long_option, WvStringParm desc, bool &val)
Add a boolean option, which, when specified, sets the specified boolean variable to true.
bool daemonize
Whether the daemon should daemonize by default (it can be changed by the default options); defaults t...
WvFile implements a stream connected to a file or Unix device.
WvString pid_file
The path to the pid file to use for the daemon; defaults to /var/run/name.pid, where name is above.
void add_reset_bool_option(char short_option, WvStringParm long_option, WvStringParm desc, bool &val)
Add a boolean option, which, when spefied, sets the specified boolean variable to false.
void restart()
Force the daemon to restart as soon as the run callback exits.
WvString is an implementation of a simple and efficient printable-string class.
WvSyslog is a descendant of WvLogRcv that sends messages to the syslogd daemon.
WvLog log
The daemon's log mechanism.
WvLogRcv adds some intelligence to WvLogRcvBase, to keep track of line-prefix-printing and other form...
WvString name
The name and version of the daemon; used for -V and logging.
void die(int status=0)
Force the daemon to exit as soon as the run callback exits.
WvAtomicFile implements a simple extension to wvfile to allow for atomic file creation.
WvDaemon - High-level abstraction for creating daemon processes.
int run(const char *argv0)
Run the daemon with no argument processing. Returns exit status.
WvLogRcv that sticks log messages in the wvcrash_ring_buffer.
bool process(int argc, char **argv, WvStringList *remaining_args=NULL)
Process the command line arguments passed to main() using the options provided through calls to add_o...
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
WvDaemonCallback load_callback
See the class description.
int num() const
Return a stdc++ string with the contents of this string.
bool want_to_die() const
Whether the daemon will quit when the run callback exits.
bool should_run() const
Whether the daemon should continue runnning.