radvd/radvd-1.8.5-Use-libdaemon-for-daemonization.patch
2012-04-12 15:58:28 +02:00

211 lines
4.8 KiB
Diff

From 9c0bb4965a916955bfec1c7702e25beb46157a5f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Thu, 5 Apr 2012 15:24:22 +0200
Subject: [PATCH] Use libdaemon for daemonization
The libc daemon(3) function suffers from race bewtween exiting parent
and saving PID into a file.
Using libdaemon library one can avoid this race and can simplify PID
file manipulation.
The only difference against older implementation is, the PID file will
be inspected, created, and removed only if daemonization is requested.
---
configure.ac | 6 +++
radvd.c | 109 +++++++++++++++++++++++++--------------------------------
2 files changed, 54 insertions(+), 61 deletions(-)
diff --git a/configure.ac b/configure.ac
index 0a6fe0d..2e001bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -137,9 +137,15 @@ AC_CHECK_LIB(c, inet_ntop,,
# prevent caching
unset ac_cv_lib_inet6_inet_ntop
+AC_CHECK_LIB([daemon], [daemon_fork], ,
+ AC_MSG_ERROR([Could not use libdaemon library])
+)
+
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS( \
+ libdaemon/dfork.h \
+ libdaemon/dpid.h \
getopt.h \
ifaddrs.h \
machine/limits.h \
diff --git a/radvd.c b/radvd.c
index 111c21c..ec37157 100644
--- a/radvd.c
+++ b/radvd.c
@@ -23,6 +23,8 @@
#endif
#include <poll.h>
+#include <libdaemon/dfork.h>
+#include <libdaemon/dpid.h>
struct Interface *IfaceList = NULL;
@@ -72,6 +74,7 @@ char usage_str[] =
extern FILE *yyin;
char *conf_file = NULL;
+char *pidfile = NULL;
char *pname;
int sock = -1;
@@ -93,15 +96,14 @@ void usage(void);
int drop_root_privileges(const char *);
int readin_config(char *);
int check_conffile_perm(const char *, const char *);
-pid_t strtopid(char const * pidstr);
-void write_pid_file(char const *);
+const char *get_pidfile(void);
void main_loop(void);
int
main(int argc, char *argv[])
{
int c, log_method;
- char *logfile, *pidfile;
+ char *logfile;
int facility;
char *username = NULL;
char *chrootdir = NULL;
@@ -110,6 +112,7 @@ main(int argc, char *argv[])
#ifdef HAVE_GETOPT_LONG
int opt_idx;
#endif
+ pid_t pid;
pname = ((pname=strrchr(argv[0],'/')) != NULL)?pname+1:argv[0];
@@ -290,16 +293,45 @@ main(int argc, char *argv[])
* lets fork now...
*/
- if (get_debuglevel() == 0) {
+ if (get_debuglevel() > 0) {
+ daemonize = 0;
+ }
- if (daemonize) {
- /* Detach from controlling terminal */
- if (daemon(0, 0) < 0)
- perror("daemon");
+ if (daemonize) {
+ if (daemon_retval_init()) {
+ flog(LOG_ERR, "Could not initialize daemon IPC.");
+ exit(1);
+ }
+
+ pid = daemon_fork();
+ if (-1 == pid) {
+ flog(LOG_ERR, "Could not fork: %s", strerror(errno));
+ daemon_retval_done();
+ exit(1);
}
- }
- write_pid_file(pidfile);
+ if (0 < pid) {
+ if (daemon_retval_wait(0)) {
+ flog(LOG_ERR, "Could not daemonize.");
+ exit(1);
+ }
+ exit(0);
+ }
+
+ daemon_pid_file_proc = get_pidfile;
+ if (daemon_pid_file_is_running() >= 0) {
+ flog(LOG_ERR, "radvd already running, terminating.");
+ daemon_retval_send(1);
+ exit(1);
+ }
+ if (daemon_pid_file_create()) {
+ flog(LOG_ERR, "Cannot create radvd PID file, terminating: %s",
+ strerror(errno));
+ daemon_retval_send(2);
+ exit(1);
+ }
+ daemon_retval_send(0);
+ }
/*
* config signal handlers
@@ -314,62 +346,17 @@ main(int argc, char *argv[])
main_loop();
flog(LOG_INFO, "sending stop adverts", pidfile);
stop_adverts();
- flog(LOG_INFO, "removing %s", pidfile);
- unlink(pidfile);
+ if (daemonize) {
+ flog(LOG_INFO, "removing %s", pidfile);
+ unlink(pidfile);
+ }
return 0;
}
-pid_t strtopid(char const * pidstr)
-{
- return atol(pidstr);
-}
-
-void write_pid_file(char const * pidfile)
-{
- int fd, ret;
- char pidstr[32];
-
- if ((fd = open(pidfile, O_RDONLY, 0)) > 0)
- {
- ret = read(fd, pidstr, sizeof(pidstr) - 1);
- if (ret < 0)
- {
- flog(LOG_ERR, "cannot read radvd pid file, terminating: %s", strerror(errno));
- exit(1);
- }
- if (ret > 0) {
- pid_t pid;
- pidstr[ret] = '\0';
- pid = strtopid(pidstr);
- if (pid > 0 && !kill(pid, 0)) {
- flog(LOG_ERR, "radvd already running, terminating.");
- exit(1);
- }
- }
- close(fd);
- fd = open(pidfile, O_CREAT|O_TRUNC|O_WRONLY, 0644);
- }
- else /* FIXME: not atomic if pidfile is on an NFS mounted volume */
- fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644);
-
- if (fd < 0)
- {
- flog(LOG_ERR, "cannot create radvd pid file, terminating: %s", strerror(errno));
- exit(1);
- }
-
- snprintf(pidstr, sizeof(pidstr), "%ld\n", (long)getpid());
-
- ret = write(fd, pidstr, strlen(pidstr));
- if (ret != strlen(pidstr))
- {
- flog(LOG_ERR, "cannot write radvd pid file, terminating: %s", strerror(errno));
- exit(1);
- }
-
- close(fd);
+const char *get_pidfile(void) {
+ return pidfile;
}
void main_loop(void)
--
1.7.7.6