Blame SOURCES/radvd-write_pid_file.patch

5481a5
diff --git a/radvd.c b/radvd.c
5481a5
index 82efe0b..508abd1 100644
5481a5
--- a/radvd.c
5481a5
+++ b/radvd.c
5481a5
@@ -17,6 +17,10 @@
5481a5
 #include "includes.h"
5481a5
 #include "radvd.h"
5481a5
 #include "pathnames.h"
5481a5
+#include <libgen.h>
5481a5
+#include <sys/file.h>
5481a5
+#include <stdio.h>
5481a5
+
5481a5
 
5481a5
 #ifdef HAVE_NETLINK
5481a5
 #include "netlink.h"
5481a5
@@ -99,6 +103,9 @@ int readin_config(char *);
5481a5
 int check_conffile_perm(const char *, const char *);
5481a5
 const char *get_pidfile(void);
5481a5
 void main_loop(void);
5481a5
+static int write_pid_file(char const *daemon_pid_file_ident, pid_t pid);
5481a5
+static int open_and_lock_pid_file(char const *daemon_pid_file_ident);
5481a5
+static void check_pid_file(char const *daemon_pid_file_ident);
5481a5
 
5481a5
 int
5481a5
 main(int argc, char *argv[])
5481a5
@@ -110,6 +117,7 @@ main(int argc, char *argv[])
5481a5
 	char *chrootdir = NULL;
5481a5
 	int configtest = 0;
5481a5
 	int daemonize = 1;
5481a5
+       int pidfd = 0;
5481a5
 #ifdef HAVE_GETOPT_LONG
5481a5
 	int opt_idx;
5481a5
 #endif
5481a5
@@ -332,6 +340,14 @@ main(int argc, char *argv[])
5481a5
 			exit(1);
5481a5
 		}
5481a5
 		daemon_retval_send(0);
5481a5
+	} else {
5481a5
+		pidfd = open_and_lock_pid_file(pidfile);
5481a5
+		if (0 != write_pid_file(pidfile, getpid())) {
5481a5
+			flog(LOG_ERR, "failure writing pid file detected");
5481a5
+			exit(-1);
5481a5
+		}
5481a5
+		check_pid_file(pidfile);
5481a5
+
5481a5
 	}
5481a5
 
5481a5
 	/*
5481a5
@@ -347,11 +363,11 @@ main(int argc, char *argv[])
5481a5
 	main_loop();
5481a5
 	flog(LOG_INFO, "sending stop adverts", pidfile);
5481a5
 	stop_adverts();
5481a5
-	if (daemonize) {
5481a5
-		flog(LOG_INFO, "removing %s", pidfile);
5481a5
-		unlink(pidfile);
5481a5
+	if (!daemonize){
5481a5
+		close(pidfd);
5481a5
 	}
5481a5
-
5481a5
+	flog(LOG_INFO, "removing %s", pidfile);
5481a5
+	unlink(pidfile);
5481a5
 	return 0;
5481a5
 }
5481a5
 
5481a5
@@ -841,3 +857,105 @@ usage(void)
5481a5
 	exit(1);
5481a5
 }
5481a5
 
5481a5
+static int open_pid_file(char const *daemon_pid_file_ident)
5481a5
+{
5481a5
+	int pidfd = open(daemon_pid_file_ident, O_SYNC | O_CREAT | O_RDWR, 0644);
5481a5
+	if (-1 == pidfd) {
5481a5
+	        flog(LOG_ERR, "unable to open pid file, %s: %s", daemon_pid_file_ident, strerror(errno));
5481a5
+		exit(-1);
5481a5
+	} else {
5481a5
+	        dlog(LOG_DEBUG, 5, "opened pid file %s", daemon_pid_file_ident);
5481a5
+	}
5481a5
+       return pidfd;
5481a5
+}
5481a5
+
5481a5
+static int open_and_lock_pid_file(char const *daemon_pid_file_ident)
5481a5
+{
5481a5
+	dlog(LOG_DEBUG, 3, "radvd startup PID is %d", getpid());
5481a5
+
5481a5
+	int pidfd = open_pid_file(daemon_pid_file_ident);
5481a5
+
5481a5
+	int lock = flock(pidfd, LOCK_EX | LOCK_NB);
5481a5
+	if (0 != lock) {
5481a5
+		flog(LOG_ERR, "unable to lock pid file, %s: %s", daemon_pid_file_ident, strerror(errno));
5481a5
+		exit(-1);
5481a5
+	} else {
5481a5
+		dlog(LOG_DEBUG, 4, "locked pid file %s", daemon_pid_file_ident);
5481a5
+	}
5481a5
+
5481a5
+	return pidfd;
5481a5
+}
5481a5
+
5481a5
+
5481a5
+static int write_pid_file(char const *daemon_pid_file_ident, pid_t pid)
5481a5
+{
5481a5
+ 	int pidfd = open_pid_file(daemon_pid_file_ident);
5481a5
+	char pid_str[20] = {""};
5481a5
+	sprintf(pid_str, "%d", pid);
5481a5
+	dlog(LOG_DEBUG, 3, "radvd PID is %s", pid_str);
5481a5
+	size_t len = strlen(pid_str);
5481a5
+	int rc = write(pidfd, pid_str, len);
5481a5
+        if (rc != (int)len) {
5481a5
+	        return -1;
5481a5
+	}
5481a5
+        char newline[] = {"\n"};
5481a5
+	len = strlen(newline);
5481a5
+	rc = write(pidfd, newline, len);
5481a5
+	if (rc != (int)len) {
5481a5
+               close(pidfd);
5481a5
+		return -1;
5481a5
+	}
5481a5
+        rc = fsync(pidfd);
5481a5
+	if (rc != 0) {
5481a5
+		dlog(LOG_DEBUG, 4, "failed to fsync pid file: %s", daemon_pid_file_ident);
5481a5
+	}
5481a5
+	rc = close(pidfd);
5481a5
+        if (rc != 0) {
5481a5
+                dlog(LOG_DEBUG, 4, "failed to close pid file: %s", daemon_pid_file_ident);
5481a5
+        }
5481a5
+        char *dirstrcopy = strdup(daemon_pid_file_ident);
5481a5
+        char *dirstr = dirname(dirstrcopy);
5481a5
+        int dirfd = open(dirstr, O_RDONLY);
5481a5
+        if (dirfd == -1){
5481a5
+           dlog(LOG_DEBUG, 4, "Failed to open directory: %s", dirstr);
5481a5
+        }
5481a5
+        rc = fsync(dirfd);
5481a5
+        if (rc != 0) {
5481a5
+                dlog(LOG_DEBUG, 4, "failed to fsync pid dir: %s", dirstr);
5481a5
+        }
5481a5
+        rc = close(dirfd);
5481a5
+        if (rc != 0) {
5481a5
+                dlog(LOG_DEBUG, 4, "failed to close pid dir: %s", dirstr);
5481a5
+        }
5481a5
+        free(dirstrcopy);
5481a5
+        dlog(LOG_DEBUG, 4, "wrote pid %d to pid file: %s", pid, daemon_pid_file_ident);
5481a5
+        return rc;
5481a5
+}
5481a5
+
5481a5
+
5481a5
+static void check_pid_file(char const *daemon_pid_file_ident)
5481a5
+{
5481a5
+	FILE *pidfile = fopen(daemon_pid_file_ident, "r");
5481a5
+
5481a5
+	if (!pidfile) {
5481a5
+		flog(LOG_ERR, "unable to open pid file, %s: %s", daemon_pid_file_ident, strerror(errno));
5481a5
+		exit(-1);
5481a5
+	}
5481a5
+
5481a5
+	pid_t pid = -1;
5481a5
+
5481a5
+	int rc = fscanf(pidfile, "%d", &pid;;
5481a5
+	fclose(pidfile);
5481a5
+
5481a5
+	if (rc != 1) {
5481a5
+		flog(LOG_ERR, "unable to read pid from pid file: %s", daemon_pid_file_ident);
5481a5
+		exit(-1);
5481a5
+	}
5481a5
+
5481a5
+	if (pid != getpid()) {
5481a5
+		flog(LOG_ERR, "pid in file, %s, doesn't match getpid(): %d != %d", daemon_pid_file_ident, pid, getpid());
5481a5
+		exit(-1);
5481a5
+	}
5481a5
+	dlog(LOG_DEBUG, 4, "validated pid file, %s: %d", daemon_pid_file_ident, pid);
5481a5
+}
5481a5
+