[radvd] Store PID before daemonizing

Petr Pisar ppisar at fedoraproject.org
Thu Apr 12 14:07:05 UTC 2012


commit 8e9d1c3480c0fe1669f71f6f4e1267cd9d851394
Author: Petr Písař <ppisar at redhat.com>
Date:   Thu Apr 12 15:58:28 2012 +0200

    Store PID before daemonizing

 radvd-1.8.5-Use-libdaemon-for-daemonization.patch  |  210 ++++++++++++++++++++
 ....8.5-Use-pkg-config-to-discover-libdaemon.patch |   66 ++++++
 radvd.spec                                         |   23 ++-
 3 files changed, 296 insertions(+), 3 deletions(-)
---
diff --git a/radvd-1.8.5-Use-libdaemon-for-daemonization.patch b/radvd-1.8.5-Use-libdaemon-for-daemonization.patch
new file mode 100644
index 0000000..4a3272a
--- /dev/null
+++ b/radvd-1.8.5-Use-libdaemon-for-daemonization.patch
@@ -0,0 +1,210 @@
+From 9c0bb4965a916955bfec1c7702e25beb46157a5f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar at 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
+
diff --git a/radvd-1.8.5-Use-pkg-config-to-discover-libdaemon.patch b/radvd-1.8.5-Use-pkg-config-to-discover-libdaemon.patch
new file mode 100644
index 0000000..ae9a518
--- /dev/null
+++ b/radvd-1.8.5-Use-pkg-config-to-discover-libdaemon.patch
@@ -0,0 +1,66 @@
+From 1cda2ef33f505be34e690d1b7a1e5eac632819af Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar at redhat.com>
+Date: Wed, 11 Apr 2012 13:52:24 +0200
+Subject: [PATCH] Use pkg-config to discover libdaemon
+
+---
+ Makefile.am  |    6 +++++-
+ README       |    2 ++
+ configure.ac |    6 +-----
+ 3 files changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 4b76a97..04b834b 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -59,8 +59,12 @@ EXTRA_radvd_SOURCES = \
+ 	netlink.h \
+ 	privsep-linux.c
+ 
++radvd_CPPFLAGS = \
++	@DAEMON_CFLAGS@
++
+ radvd_LDADD = \
+-	@CONDITIONAL_SOURCES@
++	@CONDITIONAL_SOURCES@ \
++	@DAEMON_LIBS@
+ 
+ radvd_DEPENDENCIES = \
+ 	@CONDITIONAL_SOURCES@
+diff --git a/README b/README
+index 5192c52..efa3154 100644
+--- a/README
++++ b/README
+@@ -2,6 +2,8 @@
+ Installation:
+ =============
+ 
++Install 'pkg-config' and 'libdaemon'.
++
+ Run configure, e.g.
+ 
+ ./configure --prefix=/usr/local --sysconfdir=/etc --mandir=/usr/share/man
+diff --git a/configure.ac b/configure.ac
+index b3f0a19..3ab6667 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -137,15 +137,11 @@ 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])
+-)
++PKG_CHECK_MODULES([DAEMON], libdaemon)
+ 
+ dnl Checks for header files.
+ AC_HEADER_STDC
+ AC_CHECK_HEADERS( \
+-	libdaemon/dfork.h \
+-	libdaemon/dpid.h \
+ 	getopt.h \
+ 	ifaddrs.h \
+ 	machine/limits.h \
+-- 
+1.7.7.6
+
diff --git a/radvd.spec b/radvd.spec
index 07255bc..cb4f5b2 100644
--- a/radvd.spec
+++ b/radvd.spec
@@ -1,7 +1,7 @@
 Summary:    A Router Advertisement daemon
 Name:       radvd
 Version:    1.8.5
-Release:    2%{?dist}
+Release:    3%{?dist}
 # The code includes the advertising clause, so it's GPL-incompatible
 License:    BSD with advertising
 Group:      System Environment/Daemons
@@ -9,12 +9,23 @@ URL:        http://www.litech.org/radvd/
 Source:     %{url}dist/%{name}-%{version}.tar.gz
 Source2:    radvd-tmpfs.conf
 Source3:    radvd.service
+# Bug #811997, fixed in upstream after 1.8.5
+Patch0:     radvd-1.8.5-Use-libdaemon-for-daemonization.patch
+# Bug #811997, fixed in upstream after 1.8.5
+Patch1:     radvd-1.8.5-Use-pkg-config-to-discover-libdaemon.patch
+# autoconf needed for Use-libdaemon-for-daemonization and
+# Use-pkg-config-to-discover-libdaemon patches
+BuildRequires:      autoconf
+BuildRequires:      byacc
+BuildRequires:      flex
+BuildRequires:      flex-static
+BuildRequires:      libdaemon-devel
+BuildRequires:      pkgconfig
+BuildRequires:      systemd-units
 Requires(postun):   systemd-units
 Requires(preun):    systemd-units
 Requires(post):     systemd-units
 Requires(pre):      shadow-utils
-BuildRequires:      systemd-units
-BuildRequires:      flex, flex-static, byacc
 
 %description
 radvd is the router advertisement daemon for IPv6.  It listens to router
@@ -29,6 +40,9 @@ services.
 
 %prep
 %setup -q
+%patch0 -p1 -b .libdaemon
+%patch1 -p1 -b .pkgconfig
+autoreconf -is
 for F in CHANGES; do
     iconv -f iso-8859-1 -t utf-8 < "$F" > "${F}.new"
     touch -r "$F" "${F}.new"
@@ -97,6 +111,9 @@ exit 0
 %{_sbindir}/radvdump
 
 %changelog
+* Thu Apr 12 2012 Petr Pisar <ppisar at redhat.com> - 1.8.5-3
+- Store PID before daemonizing (bug #811997)
+
 * Tue Apr 03 2012 Petr Pisar <ppisar at redhat.com> - 1.8.5-2
 - Clean up spec file
 - Remove System V init support


More information about the scm-commits mailing list