Permalink
Browse files

WIP creation of generic daemonizer with virtuals for sig handlers.

  • Loading branch information...
0 parents commit a984990b5d2f8b3e660812ffab259222f8612571 @pschwartz committed Sep 8, 2011
Showing with 344 additions and 0 deletions.
  1. +153 −0 daemon.cpp
  2. +55 −0 daemon.h
  3. +43 −0 hpccd.cbp
  4. +34 −0 hpccd.depend
  5. +10 −0 hpccd.layout
  6. +49 −0 main.cpp
  7. 0 process.cpp
  8. 0 process.h
@@ -0,0 +1,153 @@
+#include "daemon.h"
+
+#include <cerrno>
+#include <csignal>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <string>
+
+#include <fcntl.h>
+#include <syslog.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+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));
+}
+
@@ -0,0 +1,55 @@
+#ifndef DAEMON_H
+#define DAEMON_H
+
+#include <string>
+
+#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 T>
+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
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="hpccd" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build>
+ <Target title="Debug">
+ <Option output="bin/Debug/hpccd" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj/Debug/" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Compiler>
+ <Add option="-g" />
+ </Compiler>
+ </Target>
+ <Target title="Release">
+ <Option output="bin/Release/hpccd" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj/Release/" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Compiler>
+ <Add option="-O2" />
+ </Compiler>
+ <Linker>
+ <Add option="-s" />
+ </Linker>
+ </Target>
+ </Build>
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-fexceptions" />
+ </Compiler>
+ <Unit filename="daemon.cpp" />
+ <Unit filename="daemon.h" />
+ <Unit filename="main.cpp" />
+ <Extensions>
+ <code_completion />
+ <debugger />
+ </Extensions>
+ </Project>
+</CodeBlocks_project_file>
@@ -0,0 +1,34 @@
+# depslib dependency file v1.0
+1312405579 source:/home/phschwartz/src/hpccd/daemon.cpp
+ "daemon.h"
+ <cerrno>
+ <csignal>
+ <cstdio>
+ <cstdlib>
+ <cstring>
+ <iostream>
+ <string>
+ <fcntl.h>
+ <syslog.h>
+ <sys/resource.h>
+ <sys/stat.h>
+ <sys/types.h>
+ <unistd.h>
+
+1312460985 /home/phschwartz/src/hpccd/daemon.h
+ <string>
+
+1312461002 source:/home/phschwartz/src/hpccd/main.cpp
+ <cstring>
+ <cstdlib>
+ <fcntl.h>
+ <iostream>
+ <string>
+ <syslog.h>
+ <unistd.h>
+ "daemon.h"
+
+1311962916 source:/home/phschwartz/src/hpccd/process.cpp
+
+1311962896 source:/home/phschwartz/src/hpccd/service.cpp
+
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <ActiveTarget name="Debug" />
+ <File name="daemon.h" open="0" top="0" tabpos="0">
+ <Cursor position="887" topLine="14" />
+ </File>
+ <File name="main.cpp" open="0" top="0" tabpos="0">
+ <Cursor position="523" topLine="8" />
+ </File>
+</CodeBlocks_layout_file>
@@ -0,0 +1,49 @@
+#include <cstring>
+#include <cstdlib>
+#include <fcntl.h>
+#include <iostream>
+#include <string>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "daemon.h"
+
+using namespace std;
+
+class proc_d : public iProc<proc_d>{
+ 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);
+}
No changes.
No changes.

0 comments on commit a984990

Please sign in to comment.