From eb077b264f0801971e02f1fdcd62241388c7448e Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 16 Nov 2009 15:09:50 -0800 Subject: [PATCH] ovsdb-server: Maintain the database lock with --detach. 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 | 14 ++++++++++++++ lib/daemon.h | 4 +++- ovsdb/ovsdb-server.c | 22 +++++++++++++++++++--- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/daemon.c b/lib/daemon.c index e78538cb..0dcc66ff 100644 --- a/lib/daemon.c +++ b/lib/daemon.c @@ -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. */ diff --git a/lib/daemon.h b/lib/daemon.h index d0c324cf..06280ac2 100644 --- a/lib/daemon.h +++ b/lib/daemon.h @@ -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); diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c index 00c465d7..3dc59928 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -20,6 +20,7 @@ #include #include #include +#include #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); -- 2.30.2