X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdaemon.c;h=8ef5491a7dd321cfb1db98406600318807b50e21;hb=8017806940cfeaba963d6a6f51ae7573cbea6792;hp=aa971f2a8f8bd3822aad05940125fdec4e199686;hpb=aacea8ba432bdffcca77696ba407be0c62661394;p=openvswitch diff --git a/lib/daemon.c b/lib/daemon.c index aa971f2a..8ef5491a 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 #include "daemon.h" +#include #include #include #include @@ -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. */ @@ -250,16 +269,21 @@ fork_and_wait_for_startup(int *fdp) retval = waitpid(pid, &status, 0); } while (retval == -1 && errno == EINTR); - if (retval == pid - && WIFEXITED(status) - && WEXITSTATUS(status)) { - /* Child exited with an error. Convey the same error to - * our parent process as a courtesy. */ - exit(WEXITSTATUS(status)); + if (retval == pid) { + if (WIFEXITED(status) && WEXITSTATUS(status)) { + /* Child exited with an error. Convey the same error + * to our parent process as a courtesy. */ + exit(WEXITSTATUS(status)); + } else { + char *status_msg = process_status_msg(status); + VLOG_FATAL("fork child died before signaling startup (%s)", + status_msg); + } + } else if (retval < 0) { + VLOG_FATAL("waitpid failed (%s)", strerror(errno)); + } else { + NOT_REACHED(); } - - VLOG_FATAL("fork child failed to signal startup (%s)", - strerror(errno)); } close(fds[0]); *fdp = -1; @@ -397,17 +421,25 @@ 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. */ + vlog_set_levels(NULL, VLF_CONSOLE, VLL_OFF); } /* If daemonization is configured, then starts daemonization, by forking and @@ -554,7 +586,7 @@ read_pidfile__(const char *pidfile, bool delete_if_stale) * pidfile locked, and only that process has the right to unlink it. */ if (!delete_if_stale) { error = ESRCH; - VLOG_WARN("%s: pid file is stale", pidfile); + VLOG_DBG("%s: pid file is stale", pidfile); goto error; }