ofproto: Fix potential leak during flow mods.
[sliver-openvswitch.git] / lib / daemon-windows.c
index 8c284e4..f94ad9b 100644 (file)
 
 #include <config.h>
 #include "daemon.h"
+#include "daemon-private.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include "poll-loop.h"
 #include "vlog.h"
 
-VLOG_DEFINE_THIS_MODULE(daemon);
+VLOG_DEFINE_THIS_MODULE(daemon_windows);
 
 static bool service_create;          /* Was --service specified? */
 static bool service_started;         /* Have we dispatched service to start? */
@@ -30,9 +31,12 @@ static bool service_started;         /* Have we dispatched service to start? */
  * unexpectedly? */
 static bool monitor;
 
-static bool detach; /* Was --detach specified? */
-static bool detached; /* Running as the child process. */
-static HANDLE write_handle; /* End of pipe to write to parent. */
+bool detach;                 /* Was --detach specified? */
+static bool detached;        /* Running as the child process. */
+static HANDLE write_handle;  /* End of pipe to write to parent. */
+
+char *pidfile;                 /* --pidfile: Name of pidfile (null if none). */
+static FILE *filep_pidfile;    /* File pointer to access the pidfile. */
 
 /* Handle to the Services Manager and the created service. */
 static SC_HANDLE manager, service;
@@ -392,25 +396,55 @@ detach_process(int argc, char *argv[])
     exit(0);
 }
 
-/* Will daemonize() really detach? */
-bool
-get_detach()
+static void
+unlink_pidfile(void)
 {
-    return detach;
+    if (filep_pidfile) {
+        fclose(filep_pidfile);
+    }
+    if (pidfile) {
+        unlink(pidfile);
+    }
 }
 
-void
-daemon_save_fd(int fd OVS_UNUSED)
+/* If a pidfile has been configured, creates it and stores the running
+ * process's pid in it.  Ensures that the pidfile will be deleted when the
+ * process exits. */
+static void
+make_pidfile(void)
 {
-}
+    int error;
+
+    error = GetFileAttributes(pidfile);
+    if (error != INVALID_FILE_ATTRIBUTES) {
+        /* pidfile exists. Try to unlink() it. */
+        error = unlink(pidfile);
+        if (error) {
+            VLOG_FATAL("Failed to delete existing pidfile %s (%s)", pidfile,
+                       ovs_strerror(errno));
+        }
+    }
 
-void
-daemonize(void)
-{
+    filep_pidfile = fopen(pidfile, "w");
+    if (filep_pidfile == NULL) {
+        VLOG_FATAL("failed to open %s (%s)", pidfile, ovs_strerror(errno));
+    }
+
+    fatal_signal_add_hook(unlink_pidfile, NULL, NULL, true);
+
+    fprintf(filep_pidfile, "%d\n", _getpid());
+    if (fflush(filep_pidfile) == EOF) {
+        VLOG_FATAL("Failed to write into the pidfile %s", pidfile);
+    }
+
+    /* Don't close the pidfile till the process exits. */
 }
 
 void daemonize_start(void)
 {
+    if (pidfile) {
+        make_pidfile();
+    }
 }
 
 void
@@ -420,6 +454,9 @@ daemonize_complete(void)
      * communicate with the parent to inform that the child is ready. */
     if (detached) {
         int error;
+
+        close_standard_fds();
+
         error = WriteFile(write_handle, "a", 1, NULL, NULL);
         if (!error) {
             VLOG_FATAL("Failed to communicate with the parent (%s)",
@@ -429,3 +466,15 @@ daemonize_complete(void)
 
     service_complete();
 }
+
+/* Returns the file name that would be used for a pidfile if 'name' were
+ * provided to set_pidfile().  The caller must free the returned string. */
+char *
+make_pidfile_name(const char *name)
+{
+    if (name && strchr(name, ':')) {
+        return strdup(name);
+    } else {
+        return xasprintf("%s/%s.pid", ovs_rundir(), program_name);
+    }
+}