From a984990b5d2f8b3e660812ffab259222f8612571 Mon Sep 17 00:00:00 2001 From: Philip Schwartz Date: Thu, 8 Sep 2011 10:36:29 -0400 Subject: [PATCH] WIP creation of generic daemonizer with virtuals for sig handlers. --- daemon.cpp | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++ daemon.h | 55 ++++++++++++++++++ hpccd.cbp | 43 +++++++++++++++ hpccd.depend | 34 ++++++++++++ hpccd.layout | 10 ++++ main.cpp | 49 +++++++++++++++++ process.cpp | 0 process.h | 0 8 files changed, 344 insertions(+) create mode 100644 daemon.cpp create mode 100644 daemon.h create mode 100644 hpccd.cbp create mode 100644 hpccd.depend create mode 100644 hpccd.layout create mode 100644 main.cpp create mode 100644 process.cpp create mode 100644 process.h diff --git a/daemon.cpp b/daemon.cpp new file mode 100644 index 0000000..6d3d68d --- /dev/null +++ b/daemon.cpp @@ -0,0 +1,153 @@ +#include "daemon.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; + +daemond::daemond(){ + //ctor +} + +daemond::daemond(string cmd, string pidfile, sighandler sigh){ + startDaemon(cmd, pidfile, sigh); +} + +daemond::~daemond(){ + //dtor +} + +void daemond::daemonize(string cmd){ + unsigned int i; + int fd0, fd1, fd2; + pid_t pid; + struct rlimit rl; + struct sigaction sa; + + umask(0); + + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) + exit(1); + + if ((pid = fork()) < 0) + exit(1); + else if (pid != 0) + exit(0); + setsid(); + + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGHUP, &sa, NULL) < 0) + exit(1); + if ((pid = fork()) < 0) + exit(1); + else if (pid != 0) + exit(0); + + + if (chdir("/") < 0) + exit(1); + + if (rl.rlim_max == RLIM_INFINITY) + rl.rlim_max = 1024; + for (i = 0; i < rl.rlim_max; i++) + close(i); + + fd0 = open("/dev/null", O_RDWR); + fd1 = dup(0); + fd2 = dup(0); + + openlog(cmd.c_str(), LOG_CONS, LOG_DAEMON); + if (fd0 != 0 || fd1 != 1 || fd2 != 2) { + syslog(LOG_ERR, "unexpected file descriptors %d %d %d", + fd0, fd1, fd2); + exit(1); + } +} + +int daemond::running(string pidfile){ + int fd; + char buf[16]; + + fd = open(pidfile.c_str(), O_RDWR|O_CREAT, LOCKMODE); + if (fd < 0) { + syslog(LOG_ERR, "can't open %s: %s", pidfile.c_str(), strerror(errno)); + exit(1); + } + if (lockfile(fd) < 0) { + if (errno == EACCES || errno == EAGAIN) { + close(fd); + return(1); + } + syslog(LOG_ERR, "can't lock %s: %s", pidfile.c_str(), strerror(errno)); + exit(1); + } + ftruncate(fd, 0); + sprintf(buf, "%ld", (long)getpid()); + write(fd, buf, strlen(buf)+1); + return(0); +} + +void daemond::startDaemon(string cmd, string pidfile, sighandler sigh){ + struct sigaction sa; + + daemonize(cmd); + + if (running(pidfile)) { + syslog(LOG_ERR, "daemon already running"); + exit(1); + } + + pid_t pid = getpid(); + syslog(LOG_WARNING, "pid: %d", pid); + + sa.sa_handler = sigh.sigterm; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGHUP); + sa.sa_flags = 0; + if (sigaction(SIGTERM, &sa, NULL) < 0) { + syslog(LOG_ERR, "can't catch SIGTERM: %s", strerror(errno)); + exit(1); + } + + sa.sa_handler = sigh.sigint; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGHUP); + sa.sa_flags = 0; + if (sigaction(SIGINT, &sa, NULL) < 0) { + syslog(LOG_ERR, "can't catch SIGTERM: %s", strerror(errno)); + exit(1); + } + + sa.sa_handler = sigh.sighup; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGTERM); + sa.sa_flags = 0; + if (sigaction(SIGHUP, &sa, NULL) < 0) { + syslog(LOG_ERR, "can't catch SIGHUP: %s", strerror(errno)); + exit(1); + } +} + +int daemond::lockfile(int fd){ + struct flock fl; + fl.l_type = F_WRLCK; + fl.l_start = 0; + fl.l_whence = SEEK_SET; + fl.l_len = 0; + return(fcntl(fd, F_SETLK, &fl)); +} + diff --git a/daemon.h b/daemon.h new file mode 100644 index 0000000..832bf3f --- /dev/null +++ b/daemon.h @@ -0,0 +1,55 @@ +#ifndef DAEMON_H +#define DAEMON_H + +#include + +#define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) + +using namespace std; + + +struct sighandler{ + void (*sigterm)(int); + void (*sigint)(int); + void (*sighup)(int); +}; + +class daemond +{ + public: + daemond(); + daemond(string cmd, string pidfile, sighandler sigh); + virtual ~daemond(); + void startDaemon(string cmd, string pidfile, sighandler sigh); + protected: + private: + int lockfile(int fd); + void daemonize(string cmd); + int running(string pidfile); +}; + + +template +class iProc { + public: + sighandler sigh; + iProc(){ + iProcMemFn s_term = &T::sigterm; + iProcMemFn s_int = &T::sigint; + iProcMemFn s_hup = &T::sighup; + sigh.sigterm = (iProcFn)s_term; + sigh.sigint = (iProcFn)s_int; + sigh.sighup = (iProcFn)s_hup; + } + void start(string cmd, string pidfile){ + daemond *dd; + dd = new daemond(cmd,pidfile,sigh); + } + typedef void (T::*iProcMemFn)(int); + typedef void (*iProcFn)(int); + virtual void sigterm(){}; + virtual void sigint(){}; + virtual void sighup(){}; +}; + +#endif // DAEMON_H diff --git a/hpccd.cbp b/hpccd.cbp new file mode 100644 index 0000000..934d0d1 --- /dev/null +++ b/hpccd.cbp @@ -0,0 +1,43 @@ + + + + + + diff --git a/hpccd.depend b/hpccd.depend new file mode 100644 index 0000000..7d49c9b --- /dev/null +++ b/hpccd.depend @@ -0,0 +1,34 @@ +# depslib dependency file v1.0 +1312405579 source:/home/phschwartz/src/hpccd/daemon.cpp + "daemon.h" + + + + + + + + + + + + + + +1312460985 /home/phschwartz/src/hpccd/daemon.h + + +1312461002 source:/home/phschwartz/src/hpccd/main.cpp + + + + + + + + "daemon.h" + +1311962916 source:/home/phschwartz/src/hpccd/process.cpp + +1311962896 source:/home/phschwartz/src/hpccd/service.cpp + diff --git a/hpccd.layout b/hpccd.layout new file mode 100644 index 0000000..e914b3e --- /dev/null +++ b/hpccd.layout @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..970b048 --- /dev/null +++ b/main.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "daemon.h" + +using namespace std; + +class proc_d : public iProc{ + public: + proc_d():iProc(){} + + void sigterm(int signo){ + syslog(LOG_INFO, "got SIGTERM; exiting"); + exit(0); + } + + void sigint(int signo){ + syslog(LOG_INFO, "got SIGINT; exiting"); + exit(0); + } + + void sighup(int signo){ + syslog(LOG_INFO, "Re-reading configuration file"); + } +}; + +int main(int argc, char **argv){ + string cmd; + string pidfile = "/var/run/daemon/daemon.pid"; + string args(argv[0]); + size_t found = args.rfind('/'); + if ( found != string::npos ){ + cmd = args.substr(found+1); + }else{ + cmd = string(argv[0]); + } + + proc_d pd; + pd.start(cmd,pidfile); + while(1){ + sleep(30); + } + exit(0); +} diff --git a/process.cpp b/process.cpp new file mode 100644 index 0000000..e69de29 diff --git a/process.h b/process.h new file mode 100644 index 0000000..e69de29