ovsdb-server: Maintain the database lock with --detach.
authorBen Pfaff <blp@nicira.com>
Mon, 16 Nov 2009 23:09:50 +0000 (15:09 -0800)
committerBen Pfaff <blp@nicira.com>
Mon, 16 Nov 2009 23:20:01 +0000 (15:20 -0800)
Before this commit, "ovsdb-server --detach" would detach after it opened
the database file, which meant that the child process did not hold the
file lock on the database file (because a forked child process does not
inherit its parents' locks).  This commit fixes the problem by making
ovsdb-server open the database only after it has detached.  This fix, in
turn, required that daemonize() not chdir to /, because this would break
databases whose names are given relative to the current directory, and so
this commit also changes ovsdb-server to do so later.

lib/daemon.c
lib/daemon.h
ovsdb/ovsdb-server.c

index e78538cb9113e9ac4742c8cd2c43b5b47ca24825..0dcc66ff742c10e48275f4adb9694a6712c93850 100644 (file)
@@ -81,6 +81,13 @@ set_no_chdir(void)
     chdir_ = false;
 }
 
+/* Will we chdir to "/" as part of daemonizing? */
+bool
+is_chdir_enabled(void)
+{
+    return chdir_;
+}
+
 /* Normally, die_if_already_running() will terminate the program with a message
  * if a locked pidfile already exists.  If this function is called,
  * die_if_already_running() will merely log a warning. */
@@ -98,6 +105,13 @@ set_detach(void)
     detach = true;
 }
 
+/* Will daemonize() really detach? */
+bool
+get_detach(void)
+{
+    return detach;
+}
+
 /* If a pidfile has been configured and that pidfile already exists and is
  * locked by a running process, returns the pid of the running process.
  * Otherwise, returns 0. */
index d0c324cfc3906ffb9a8ef5df6981a7be3043806e..06280ac24c3dbf60d2874f1d64354a36d7f50306 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Nicira Networks.
+ * Copyright (c) 2008, 2009 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -55,7 +55,9 @@ char *make_pidfile_name(const char *name);
 void set_pidfile(const char *name);
 const char *get_pidfile(void);
 void set_no_chdir(void);
+bool is_chdir_enabled(void);
 void set_detach(void);
+bool get_detach(void);
 void daemonize(void);
 void die_if_already_running(void);
 void ignore_existing_pidfile(void);
index 00c465d76bcd833252c1c74efbb520ea6f6b6b0c..3dc59928046c63076f3824e9a400fa4465a74da1 100644 (file)
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <getopt.h>
 #include <signal.h>
+#include <unistd.h>
 
 #include "command-line.h"
 #include "daemon.h"
@@ -59,6 +60,7 @@ main(int argc, char *argv[])
     struct ovsdb *db;
     const char *name;
     char *file_name;
+    bool do_chdir;
     int retval;
     size_t i;
 
@@ -71,6 +73,20 @@ main(int argc, char *argv[])
 
     parse_options(argc, argv, &file_name, &active, &passive);
 
+    if (get_detach() && is_chdir_enabled()) {
+        /* We need to skip chdir("/") in daemonize() and do it later, because
+         * we need to open the database and possible set up up Unix domain
+         * sockets in the current working directory after we daemonize.  We
+         * can't open the database before we daemonize because file locks
+         * aren't inherited by child processes.  */
+        do_chdir = true;
+        set_no_chdir();
+    } else {
+        do_chdir = false;
+    }
+    die_if_already_running();
+    daemonize();
+
     error = ovsdb_file_open(file_name, false, &db);
     if (error) {
         ovs_fatal(0, "%s", ovsdb_error_to_string(error));
@@ -89,14 +105,14 @@ main(int argc, char *argv[])
     svec_destroy(&active);
     svec_destroy(&passive);
 
-    die_if_already_running();
-    daemonize();
-
     retval = unixctl_server_create(NULL, &unixctl);
     if (retval) {
         ovs_fatal(retval, "could not listen for control connections");
     }
 
+    if (do_chdir) {
+        chdir("/");
+    }
     for (;;) {
         ovsdb_jsonrpc_server_run(jsonrpc);
         unixctl_server_run(unixctl);