This eliminates a kluge that was duplicated in three different daemons.
Signed-off-by: Ben Pfaff <[email protected]>
---
lib/daemon.c | 36 ++++++++++++++++++++++++++++++------
lib/daemon.h | 3 ++-
ovsdb/ovsdb-client.c | 8 ++------
tests/test-netflow.c | 11 ++---------
utilities/ovs-ofctl.c | 10 ++--------
5 files changed, 38 insertions(+), 30 deletions(-)
diff --git a/lib/daemon.c b/lib/daemon.c
index 3dd5a1a..8ef5491 100644
--- a/lib/daemon.c
+++ b/lib/daemon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
#include <config.h>
#include "daemon.h"
+#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
@@ -61,6 +62,10 @@ static int daemonize_fd = -1;
* it dies due to an error signal? */
static bool monitor;
+/* For each of the standard file descriptors, whether to replace it by
+ * /dev/null (if false) or keep it for the daemon to use (if true). */
+static bool save_fds[3];
+
static void check_already_running(void);
static int lock_pidfile(FILE *, int command);
@@ -142,6 +147,20 @@ daemon_set_monitor(void)
monitor = true;
}
+/* A daemon doesn't normally have any use for the file descriptors for stdin,
+ * stdout, and stderr after it detaches. To keep these file descriptors from
+ * e.g. holding an SSH session open, by default detaching replaces each of
+ * these file descriptors by /dev/null. But a few daemons expect the user to
+ * redirect stdout or stderr to a file, in which case it is desirable to keep
+ * these file descriptors. This function, therefore, disables replacing 'fd'
+ * by /dev/null when the daemon detaches. */
+void
+daemon_save_fd(int fd)
+{
+ assert(fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO);
+ save_fds[fd] = true;
+}
+
/* 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. */
@@ -402,16 +421,21 @@ monitor_daemon(pid_t daemon_pid)
program_name = saved_program_name;
}
-/* Close stdin, stdout, stderr. If we're started from e.g. an SSH session,
- * then this keeps us from holding that session open artificially. */
+/* Close standard file descriptors (except any that the client has requested we
+ * leave open by calling daemon_save_fd()). If we're started from e.g. an SSH
+ * session, then this keeps us from holding that session open artificially. */
static void
close_standard_fds(void)
{
int null_fd = get_null_fd();
if (null_fd >= 0) {
- dup2(null_fd, STDIN_FILENO);
- dup2(null_fd, STDOUT_FILENO);
- dup2(null_fd, STDERR_FILENO);
+ int fd;
+
+ for (fd = 0; fd < 3; fd++) {
+ if (!save_fds[fd]) {
+ dup2(null_fd, fd);
+ }
+ }
}
/* Disable logging to stderr to avoid wasting CPU time. */
diff --git a/lib/daemon.h b/lib/daemon.h
index eb38d5d..1b4f988 100644
--- a/lib/daemon.h
+++ b/lib/daemon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,6 +64,7 @@ bool is_chdir_enabled(void);
void set_detach(void);
bool get_detach(void);
void daemon_set_monitor(void);
+void daemon_save_fd(int fd);
void daemonize(void);
void daemonize_start(void);
void daemonize_complete(void);
diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c
index d2a9de1..03dd6c0 100644
--- a/ovsdb/ovsdb-client.c
+++ b/ovsdb/ovsdb-client.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -722,12 +722,8 @@ do_monitor(struct jsonrpc *rpc, const char *database,
monitor_print(msg->result, table, &columns, true);
fflush(stdout);
if (get_detach()) {
- /* daemonize() closes the standard file descriptors. We output
- * to stdout, so we need to save and restore STDOUT_FILENO. */
- int fd = dup(STDOUT_FILENO);
+ daemon_save_fd(STDOUT_FILENO);
daemonize();
- dup2(fd, STDOUT_FILENO);
- close(fd);
}
} else if (msg->type == JSONRPC_NOTIFY
&& !strcmp(msg->method, "update")) {
diff --git a/tests/test-netflow.c b/tests/test-netflow.c
index 5a88ada..b85c663 100644
--- a/tests/test-netflow.c
+++ b/tests/test-netflow.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 Nicira Networks.
+ * Copyright (c) 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -190,7 +190,6 @@ main(int argc, char *argv[])
bool exiting = false;
int error;
int sock;
- int fd;
int n;
proctitle_init(argc, argv);
@@ -208,10 +207,7 @@ main(int argc, char *argv[])
ovs_fatal(0, "%s: failed to open (%s)", argv[1], strerror(-sock));
}
- /* Daemonization will close stdout but we really want to keep it, so make a
- * copy. */
- fd = dup(STDOUT_FILENO);
-
+ daemon_save_fd(STDOUT_FILENO);
daemonize_start();
error = unixctl_server_create(NULL, &server);
@@ -222,9 +218,6 @@ main(int argc, char *argv[])
daemonize_complete();
- /* Now get stdout back. */
- dup2(fd, STDOUT_FILENO);
-
ofpbuf_init(&buf, MAX_RECV);
n = 0;
for (;;) {
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 3d3a7b7..d14575e 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -828,12 +828,9 @@ monitor_vconn(struct vconn *vconn)
{
struct unixctl_server *server;
bool exiting = false;
- int error, fd;
-
- /* Daemonization will close stderr but we really want to keep it, so make a
- * copy. */
- fd = dup(STDERR_FILENO);
+ int error;
+ daemon_save_fd(STDERR_FILENO);
daemonize_start();
error = unixctl_server_create(NULL, &server);
if (error) {
@@ -842,9 +839,6 @@ monitor_vconn(struct vconn *vconn)
unixctl_command_register("exit", "", 0, 0, ofctl_exit, &exiting);
daemonize_complete();
- /* Now get stderr back. */
- dup2(fd, STDERR_FILENO);
-
for (;;) {
struct ofpbuf *b;
int retval;
--
1.7.2.5
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev