patch: Remove veth driver.
[sliver-openvswitch.git] / lib / daemon.c
index 8629114..78f88a0 100644 (file)
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include "command-line.h"
 #include "fatal-signal.h"
 #include "dirs.h"
 #include "lockfile.h"
@@ -57,9 +58,9 @@ static bool monitor;
 char *
 make_pidfile_name(const char *name) 
 {
-    return (!name ? xasprintf("%s/%s.pid", ovs_rundir, program_name)
-            : *name == '/' ? xstrdup(name)
-            : xasprintf("%s/%s", ovs_rundir, name));
+    return (!name
+            ? xasprintf("%s/%s.pid", ovs_rundir, program_name)
+            : abs_file_name(ovs_rundir, name));
 }
 
 /* Sets up a following call to daemonize() to create a pidfile named 'name'.
@@ -322,16 +323,23 @@ should_restart(int status)
 static void
 monitor_daemon(pid_t daemon_pid)
 {
-    /* XXX Should limit the rate at which we restart the daemon. */
     /* XXX Should log daemon's stderr output at startup time. */
     const char *saved_program_name;
+    time_t last_restart;
+    char *status_msg;
 
     saved_program_name = program_name;
     program_name = xasprintf("monitor(%s)", program_name);
+    status_msg = xstrdup("healthy");
+    last_restart = TIME_MIN;
     for (;;) {
         int retval;
         int status;
 
+        proctitle_set("%s: monitoring pid %lu (%s)",
+                      saved_program_name, (unsigned long int) daemon_pid,
+                      status_msg);
+
         do {
             retval = waitpid(daemon_pid, &status, 0);
         } while (retval == -1 && errno == EINTR);
@@ -339,25 +347,55 @@ monitor_daemon(pid_t daemon_pid)
         if (retval == -1) {
             ovs_fatal(errno, "waitpid failed");
         } else if (retval == daemon_pid) {
-            char *status_msg = process_status_msg(status);
+            char *s = process_status_msg(status);
+            free(status_msg);
+            status_msg = xasprintf("pid %lu died, %s",
+                                   (unsigned long int) daemon_pid, s);
+            free(s);
+
             if (should_restart(status)) {
-                VLOG_ERR("%s daemon died unexpectedly (%s), restarting",
-                         saved_program_name, status_msg);
-                free(status_msg);
+                if (WCOREDUMP(status)) {
+                    /* Disable further core dumps to save disk space. */
+                    struct rlimit r;
+
+                    r.rlim_cur = 0;
+                    r.rlim_max = 0;
+                    if (setrlimit(RLIMIT_CORE, &r) == -1) {
+                        VLOG_WARN("failed to disable core dumps: %s",
+                                  strerror(errno));
+                    }
+                }
+
+                /* Throttle restarts to no more than once every 10 seconds. */
+                if (time(NULL) < last_restart + 10) {
+                    VLOG_WARN("%s, waiting until 10 seconds since last "
+                              "restart", status_msg);
+                    for (;;) {
+                        time_t now = time(NULL);
+                        time_t wakeup = last_restart + 10;
+                        if (now >= wakeup) {
+                            break;
+                        }
+                        sleep(wakeup - now);
+                    }
+                }
+                last_restart = time(NULL);
 
+                VLOG_ERR("%s, restarting", status_msg);
                 daemon_pid = fork_and_wait_for_startup(&daemonize_fd);
                 if (!daemon_pid) {
                     break;
                 }
             } else {
-                VLOG_INFO("%s daemon exited normally (%s), exiting",
-                          saved_program_name, status_msg);
+                VLOG_INFO("%s, exiting", status_msg);
                 exit(0);
             }
         }
     }
+    free(status_msg);
 
     /* Running in new daemon process. */
+    proctitle_restore();
     free((char *) program_name);
     program_name = saved_program_name;
 }