[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