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);
73 void WvDaemon::init(WvStringParm _name,
74 WvStringParm _version,
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 *)