Skip to content

Commit

Permalink
WIP creation of generic daemonizer with virtuals for sig handlers.
Browse files Browse the repository at this point in the history
  • Loading branch information
pschwartz committed Sep 8, 2011
0 parents commit a984990
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 0 deletions.
153 changes: 153 additions & 0 deletions daemon.cpp
@@ -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));
}

55 changes: 55 additions & 0 deletions daemon.h
@@ -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
43 changes: 43 additions & 0 deletions hpccd.cbp
@@ -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>
34 changes: 34 additions & 0 deletions hpccd.depend
@@ -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

10 changes: 10 additions & 0 deletions hpccd.layout
@@ -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>
49 changes: 49 additions & 0 deletions main.cpp
@@ -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);
}
Empty file added process.cpp
Empty file.
Empty file added process.h
Empty file.

0 comments on commit a984990

Please sign in to comment.