Under most circumstances, rrdcached can detect a stale pid file.
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Tue, 14 Oct 2008 19:23:24 +0000 (19:23 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Tue, 14 Oct 2008 19:23:24 +0000 (19:23 +0000)
If the process in the pid file does not exist, or cannot be signalled by
the rrdcached owner, then rrdcached will replace the pid file and start
normally.  Otherwise, it will complain verbosely to STDERR.

--kevin

git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1605 a5681a0c-68f1-0310-ab6d-d61299d08faa

src/rrd_daemon.c

index 511b04e..9fbbc11 100644 (file)
@@ -286,7 +286,7 @@ static void install_signal_handlers(void) /* {{{ */
 
 } /* }}} void install_signal_handlers */
 
-static int open_pidfile(void) /* {{{ */
+static int open_pidfile(char *action, int oflag) /* {{{ */
 {
   int fd;
   char *file;
@@ -295,14 +295,52 @@ static int open_pidfile(void) /* {{{ */
     ? config_pid_file
     : LOCALSTATEDIR "/run/rrdcached.pid";
 
-  fd = open(file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IRGRP|S_IROTH);
+  fd = open(file, oflag, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH);
   if (fd < 0)
-    fprintf(stderr, "FATAL: cannot create '%s' (%s)\n",
-            file, rrd_strerror(errno));
+    fprintf(stderr, "rrdcached: can't %s pid file '%s' (%s)\n",
+            action, file, rrd_strerror(errno));
 
   return(fd);
 } /* }}} static int open_pidfile */
 
+/* check existing pid file to see whether a daemon is running */
+static int check_pidfile(void)
+{
+  int pid_fd;
+  pid_t pid;
+  char pid_str[16];
+
+  pid_fd = open_pidfile("open", O_RDWR);
+  if (pid_fd < 0)
+    return pid_fd;
+
+  if (read(pid_fd, pid_str, sizeof(pid_str)) <= 0)
+    return -1;
+
+  pid = atoi(pid_str);
+  if (pid <= 0)
+    return -1;
+
+  /* another running process that we can signal COULD be
+   * a competing rrdcached */
+  if (pid != getpid() && kill(pid, 0) == 0)
+  {
+    fprintf(stderr,
+            "FATAL: Another rrdcached daemon is running?? (pid %d)\n", pid);
+    close(pid_fd);
+    return -1;
+  }
+
+  lseek(pid_fd, 0, SEEK_SET);
+  ftruncate(pid_fd, 0);
+
+  fprintf(stderr,
+          "rrdcached: removed stale PID file (no rrdcached on pid %d)\n"
+          "rrdcached: starting normally.\n", pid);
+
+  return pid_fd;
+} /* }}} static int check_pidfile */
+
 static int write_pidfile (int fd) /* {{{ */
 {
   pid_t pid;
@@ -2318,13 +2356,16 @@ static void *listen_thread_main (void *args __attribute__((unused))) /* {{{ */
 static int daemonize (void) /* {{{ */
 {
   int status;
-  int fd;
+  int pid_fd;
   char *base_dir;
 
   daemon_uid = geteuid();
 
-  fd = open_pidfile();
-  if (fd < 0) return fd;
+  pid_fd = open_pidfile("create", O_CREAT|O_EXCL|O_WRONLY);
+  if (pid_fd < 0)
+    pid_fd = check_pidfile();
+  if (pid_fd < 0)
+    return pid_fd;
 
   if (!stay_foreground)
   {
@@ -2377,7 +2418,7 @@ static int daemonize (void) /* {{{ */
     return (-1);
   }
 
-  status = write_pidfile (fd);
+  status = write_pidfile (pid_fd);
   return status;
 } /* }}} int daemonize */