daemon: Close standard file descriptors after detach for windows.
authorGurucharan Shetty <gshetty@nicira.com>
Wed, 23 Apr 2014 17:28:00 +0000 (10:28 -0700)
committerGurucharan Shetty <gshetty@nicira.com>
Thu, 24 Apr 2014 21:43:37 +0000 (14:43 -0700)
In the unit tests, we check for some logs stored in stderr. In case
of windows, unit tests fail because the child writes additional information
into stderr because it does not have it closed. This commit
closes standard file descriptors for windows too.

Because the functions related to closing file descriptors is common
for both windows and unix, add it to the common daemonization file
daemon.c

Signed-off-by: Gurucharan Shetty <gshetty@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
lib/automake.mk
lib/daemon-unix.c
lib/daemon-windows.c
lib/daemon.c [new file with mode: 0644]
lib/daemon.h

index e904f88..519d243 100644 (file)
@@ -45,6 +45,7 @@ lib_libopenvswitch_la_SOURCES = \
        lib/crc32c.h \
        lib/csum.c \
        lib/csum.h \
        lib/crc32c.h \
        lib/csum.c \
        lib/csum.h \
+       lib/daemon.c \
        lib/daemon.h \
        lib/dhcp.h \
        lib/dummy.c \
        lib/daemon.h \
        lib/dhcp.h \
        lib/dummy.c \
index 74914a4..4dcb696 100644 (file)
@@ -63,10 +63,6 @@ static int daemonize_fd = -1;
  * it dies due to an error signal? */
 static bool monitor;
 
  * 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);
 static char *make_pidfile_name(const char *name);
 static void check_already_running(void);
 static int lock_pidfile(FILE *, int command);
 static char *make_pidfile_name(const char *name);
@@ -136,22 +132,6 @@ daemon_set_monitor(void)
     monitor = true;
 }
 
     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)
-{
-    ovs_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. */
 /* 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. */
@@ -441,47 +421,6 @@ monitor_daemon(pid_t daemon_pid)
     set_subprogram_name("");
 }
 
     set_subprogram_name("");
 }
 
-/* Returns a readable and writable fd for /dev/null, if successful, otherwise
- * a negative errno value.  The caller must not close the returned fd (because
- * the same fd will be handed out to subsequent callers). */
-static int
-get_null_fd(void)
-{
-    static int null_fd;
-
-    if (!null_fd) {
-        null_fd = open("/dev/null", O_RDWR);
-        if (null_fd < 0) {
-            int error = errno;
-            VLOG_ERR("could not open /dev/null: %s", ovs_strerror(error));
-            null_fd = -error;
-        }
-    }
-
-    return null_fd;
-}
-
-/* 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) {
-        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. */
-    vlog_set_levels(NULL, VLF_CONSOLE, VLL_OFF);
-}
-
 /* If daemonization is configured, then starts daemonization, by forking and
  * returning in the child process.  The parent process hangs around until the
  * child lets it know either that it completed startup successfully (by calling
 /* If daemonization is configured, then starts daemonization, by forking and
  * returning in the child process.  The parent process hangs around until the
  * child lets it know either that it completed startup successfully (by calling
index f059fc5..4d33b8c 100644 (file)
@@ -402,11 +402,6 @@ get_detach()
     return detach;
 }
 
     return detach;
 }
 
-void
-daemon_save_fd(int fd OVS_UNUSED)
-{
-}
-
 void
 daemonize(void)
 {
 void
 daemonize(void)
 {
@@ -472,6 +467,9 @@ daemonize_complete(void)
      * communicate with the parent to inform that the child is ready. */
     if (detached) {
         int error;
      * 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)",
         error = WriteFile(write_handle, "a", 1, NULL, NULL);
         if (!error) {
             VLOG_FATAL("Failed to communicate with the parent (%s)",
diff --git a/lib/daemon.c b/lib/daemon.c
new file mode 100644 (file)
index 0000000..546612c
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2014 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <config.h>
+#include "daemon.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(daemon);
+
+/* 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];
+
+/* 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)
+{
+    ovs_assert(fd == STDIN_FILENO ||
+               fd == STDOUT_FILENO ||
+               fd == STDERR_FILENO);
+    save_fds[fd] = true;
+}
+
+/* Returns a readable and writable fd for /dev/null, if successful, otherwise
+ * a negative errno value.  The caller must not close the returned fd (because
+ * the same fd will be handed out to subsequent callers). */
+static int
+get_null_fd(void)
+{
+    static int null_fd;
+#ifndef _WIN32
+    char *device = "/dev/null";
+#else
+    char *device = "nul";
+#endif
+
+    if (!null_fd) {
+        null_fd = open(device, O_RDWR);
+        if (null_fd < 0) {
+            int error = errno;
+            VLOG_ERR("could not open %s: %s", device, ovs_strerror(error));
+            null_fd = -error;
+        }
+    }
+
+    return null_fd;
+}
+
+/* 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. */
+void
+close_standard_fds(void)
+{
+    int null_fd = get_null_fd();
+    if (null_fd >= 0) {
+        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. */
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_OFF);
+}
index a5f99d5..875569d 100644 (file)
@@ -129,5 +129,6 @@ void service_start(int *argcp, char **argvp[]);
 void service_stop(void);
 bool should_service_stop(void);
 void set_pidfile(const char *name);
 void service_stop(void);
 bool should_service_stop(void);
 void set_pidfile(const char *name);
+void close_standard_fds(void);
 
 #endif /* daemon.h */
 
 #endif /* daemon.h */