X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fdaemon.c;h=e7ee56ce1207aeda07b0688c81a7fb6e93080440;hb=485e2766d816a18e1a51ddf5e12e55f38aeedf89;hp=71f6f81158542a957405827e0f2b7947c3492536;hpb=7a97619ae4484604c15b846ce7268094e048729a;p=sliver-openvswitch.git diff --git a/lib/daemon.c b/lib/daemon.c index 71f6f8115..e7ee56ce1 100644 --- a/lib/daemon.c +++ b/lib/daemon.c @@ -16,7 +16,6 @@ #include #include "daemon.h" -#include #include #include #include @@ -158,7 +157,9 @@ daemon_set_monitor(void) void daemon_save_fd(int fd) { - assert(fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO); + ovs_assert(fd == STDIN_FILENO || + fd == STDOUT_FILENO || + fd == STDERR_FILENO); save_fds[fd] = true; } @@ -175,57 +176,63 @@ make_pidfile(void) int error; /* Create a temporary pidfile. */ - tmpfile = xasprintf("%s.tmp%ld", pidfile, pid); - fatal_signal_add_file_to_unlink(tmpfile); - file = fopen(tmpfile, "w+"); + if (overwrite_pidfile) { + tmpfile = xasprintf("%s.tmp%ld", pidfile, pid); + fatal_signal_add_file_to_unlink(tmpfile); + } else { + /* Everyone shares the same file which will be treated as a lock. To + * avoid some uncomfortable race conditions, we can't set up the fatal + * signal unlink until we've acquired it. */ + tmpfile = xasprintf("%s.tmp", pidfile); + } + + file = fopen(tmpfile, "a+"); if (!file) { VLOG_FATAL("%s: create failed (%s)", tmpfile, strerror(errno)); } + error = lock_pidfile(file, F_SETLK); + if (error) { + /* Looks like we failed to acquire the lock. Note that, if we failed + * for some other reason (and '!overwrite_pidfile'), we will have + * left 'tmpfile' as garbage in the file system. */ + VLOG_FATAL("%s: fcntl(F_SETLK) failed (%s)", tmpfile, strerror(error)); + } + + if (!overwrite_pidfile) { + /* We acquired the lock. Make sure to clean up on exit, and verify + * that we're allowed to create the actual pidfile. */ + fatal_signal_add_file_to_unlink(tmpfile); + check_already_running(); + } + if (fstat(fileno(file), &s) == -1) { VLOG_FATAL("%s: fstat failed (%s)", tmpfile, strerror(errno)); } + if (ftruncate(fileno(file), 0) == -1) { + VLOG_FATAL("%s: truncate failed (%s)", tmpfile, strerror(errno)); + } + fprintf(file, "%ld\n", pid); if (fflush(file) == EOF) { VLOG_FATAL("%s: write failed (%s)", tmpfile, strerror(errno)); } - error = lock_pidfile(file, F_SETLK); - if (error) { - VLOG_FATAL("%s: fcntl(F_SETLK) failed (%s)", tmpfile, strerror(error)); - } + error = rename(tmpfile, pidfile); - /* Rename or link it to the correct name. */ - if (overwrite_pidfile) { - if (rename(tmpfile, pidfile) < 0) { - VLOG_FATAL("failed to rename \"%s\" to \"%s\" (%s)", - tmpfile, pidfile, strerror(errno)); - } - } else { - do { - error = link(tmpfile, pidfile) == -1 ? errno : 0; - if (error == EEXIST) { - check_already_running(); - } - } while (error == EINTR || error == EEXIST); - if (error) { - VLOG_FATAL("failed to link \"%s\" as \"%s\" (%s)", - tmpfile, pidfile, strerror(error)); - } + /* Due to a race, 'tmpfile' may be owned by a different process, so we + * shouldn't delete it on exit. */ + fatal_signal_remove_file_to_unlink(tmpfile); + + if (error < 0) { + VLOG_FATAL("failed to rename \"%s\" to \"%s\" (%s)", + tmpfile, pidfile, strerror(errno)); } /* Ensure that the pidfile will get deleted on exit. */ fatal_signal_add_file_to_unlink(pidfile); - /* Delete the temporary pidfile if it still exists. */ - if (!overwrite_pidfile) { - error = fatal_signal_unlink_file_now(tmpfile); - if (error) { - VLOG_FATAL("%s: unlink failed (%s)", tmpfile, strerror(error)); - } - } - /* Clean up. * * We don't close 'file' because its file descriptor must remain open to @@ -486,7 +493,9 @@ daemonize_start(void) /* Running in parent process. */ exit(0); } + /* Running in daemon or monitor process. */ + setsid(); } if (monitor) { @@ -540,7 +549,6 @@ void daemonize_post_detach(void) { if (detach) { - setsid(); if (chdir_) { ignore(chdir("/")); }