diff --git a/daemon/.gitignore b/daemon/.gitignore index 6693f26..fa58ad5 100644 --- a/daemon/.gitignore +++ b/daemon/.gitignore @@ -4,3 +4,4 @@ alix-usv alix-usvd alix-usvd.sock alix-usvd.log +alix-usvd.pid diff --git a/daemon/Makefile b/daemon/Makefile index 42bb51f..a280870 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -6,7 +6,7 @@ CFLAGS = -Wall -O2 -MD -MP -MF $(*F).d # ------ SRC1 := alix-usv.c logging.c unixsocket.c -SRC2 := alix-usvd.c configfile.c event.c logging.c unixsocket.c +SRC2 := alix-usvd.c configfile.c event.c logging.c pidfile.c unixsocket.c all: $(TARGET1) $(TARGET2) @@ -23,6 +23,6 @@ $(TARGET2): $(SRC2:.c=.o) @$(CC) -c $(CFLAGS) $< -o $@ clean: - rm -rf $(TARGET1) $(TARGET2) *.o *.d *.log *.sock + rm -rf $(TARGET1) $(TARGET2) *.o *.d *.log *.sock *.pid -include $(shell find . -name \*.d 2> /dev/null) diff --git a/daemon/alix-usvd.c b/daemon/alix-usvd.c index ed3af1f..c463d73 100644 --- a/daemon/alix-usvd.c +++ b/daemon/alix-usvd.c @@ -34,6 +34,7 @@ #include "configfile.h" #include "event.h" #include "logging.h" +#include "pidfile.h" #include "unixsocket.h" /* eeprom parameters / thresholds & defaults */ @@ -41,6 +42,7 @@ #define DEFAULT_CONFIG "alix-usvd.conf" #define DEFAULT_LOGFILE "alix-usvd.log" +#define DEFAULT_PIDFILE "alix-usvd.pid" #define DEFAULT_SOCKET "alix-usvd.sock" enum { @@ -370,7 +372,12 @@ int main(int argc, char *argv[]) exit(1); if (debug == 0) { - /* TODO: check PID-file */ + /* check pidfile */ + const char *pidfile = config_get_string("global", "pidfile", DEFAULT_PIDFILE); + if (pidfile_check(pidfile, 1) != 0) { + log_print(LOG_ERROR, "alix-usvd already running"); + exit(1); + } /* start logging */ const char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE); @@ -380,7 +387,11 @@ int main(int argc, char *argv[]) /* zum daemon mutieren */ daemon(-1, 0); - /* TODO: write PID-file */ + /* create pidfile */ + if (pidfile_create(pidfile) < 0) { + log_print(LOG_ERROR, "failed to create pidfile %s", pidfile); + exit(1); + } } log_print(LOG_INFO, "alix-usvd started (pid: %d)", getpid()); diff --git a/daemon/pidfile.c b/daemon/pidfile.c new file mode 100644 index 0000000..9de2d3d --- /dev/null +++ b/daemon/pidfile.c @@ -0,0 +1,71 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "logging.h" + +int pidfile_create(const char *filename) +{ + int fd = open(filename, O_CREAT | O_EXCL | O_RDWR, 0644); + if (fd < 0) + return -1; + + char buf[8]; + int len = snprintf(buf, sizeof(buf), "%d", getpid()); + write(fd, buf, len); + + close(fd); + return 0; +} + +int pidfile_remove(const char *filename) +{ + return unlink(filename); +} + +pid_t pidfile_check(const char *filename, int remove_stale) +{ + int fd = open(filename, O_RDWR); + if (fd < 0) { + if (errno == ENOENT) { + errno = 0; + return 0; + } + return -1; + } + + char buf[9]; + int len = read(fd, buf, sizeof(buf) -1); + buf[len] = '\0'; + + char *tmp; + pid_t pid = strtol(buf, &tmp, 10); + if (len == 0 || tmp == buf) + pid = -1; + + /* just return the pid */ + if (!remove_stale) + return pid; + + /* invalid pid, remove stale file */ + if (pid == -1) { + pidfile_remove(filename); + return 0; + } + + /* check if pid is still running */ + if (kill(pid, 0) == 0 || errno != ESRCH) { + errno = 0; + return pid; + } + + errno = 0; + pidfile_remove(filename); + return 0; +} diff --git a/daemon/pidfile.h b/daemon/pidfile.h new file mode 100644 index 0000000..2ba1512 --- /dev/null +++ b/daemon/pidfile.h @@ -0,0 +1,11 @@ +#ifndef _PIDFILE_H_ +#define _PIDFILE_H_ + +#include + +int pidfile_create(const char *filename); +int pidfile_remove(const char *filename); + +pid_t pidfile_check(const char *filename, int remove_stale); + +#endif // _PIDFILE_H_