X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdaemon.c;h=2f6f08192016c03827047a14f4cc1c0e0b917e4e;hb=55eccb868b8f1da858a9f724335b5bb059276497;hp=6b61879dbb76723a926dea8683716bc39eaacca7;hpb=cbbdf81cf8bfcc87e141f66b93bf3bcf1220bff8;p=openvswitch diff --git a/lib/daemon.c b/lib/daemon.c index 6b61879d..2f6f0819 100644 --- a/lib/daemon.c +++ b/lib/daemon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "command-line.h" #include "fatal-signal.h" @@ -34,7 +35,7 @@ #include "util.h" #include "vlog.h" -VLOG_DEFINE_THIS_MODULE(daemon) +VLOG_DEFINE_THIS_MODULE(daemon); /* --detach: Should we run in the background? */ static bool detach; @@ -42,6 +43,10 @@ static bool detach; /* --pidfile: Name of pidfile (null if none). */ static char *pidfile; +/* Device and inode of pidfile, so we can avoid reopening it. */ +static dev_t pidfile_dev; +static ino_t pidfile_ino; + /* --overwrite-pidfile: Create pidfile even if one already exists and is locked? */ static bool overwrite_pidfile; @@ -62,8 +67,8 @@ char * make_pidfile_name(const char *name) { return (!name - ? xasprintf("%s/%s.pid", ovs_rundir, program_name) - : abs_file_name(ovs_rundir, name)); + ? xasprintf("%s/%s.pid", ovs_rundir(), program_name) + : abs_file_name(ovs_rundir(), name)); } /* Sets up a following call to daemonize() to create a pidfile named 'name'. @@ -208,12 +213,21 @@ make_pidfile(void) close(fd); } else { /* Keep 'fd' open to retain the lock. */ + struct stat s; + + if (!fstat(fd, &s)) { + pidfile_dev = s.st_dev; + pidfile_ino = s.st_ino; + } else { + VLOG_ERR("%s: fstat failed: %s", + pidfile, strerror(errno)); + } } - free(text); } else { VLOG_ERR("%s: write failed: %s", tmpfile, strerror(errno)); close(fd); } + free(text); } else { VLOG_ERR("%s: fcntl failed: %s", tmpfile, strerror(errno)); close(fd); @@ -353,13 +367,13 @@ monitor_daemon(pid_t daemon_pid) ovs_fatal(errno, "waitpid failed"); } else if (retval == daemon_pid) { char *s = process_status_msg(status); - free(status_msg); - status_msg = xasprintf("%d crashes: pid %lu died, %s", - ++crashes, - (unsigned long int) daemon_pid, s); - free(s); - if (should_restart(status)) { + free(status_msg); + status_msg = xasprintf("%d crashes: pid %lu died, %s", + ++crashes, + (unsigned long int) daemon_pid, s); + free(s); + if (WCOREDUMP(status)) { /* Disable further core dumps to save disk space. */ struct rlimit r; @@ -393,7 +407,9 @@ monitor_daemon(pid_t daemon_pid) break; } } else { - VLOG_INFO("%s, exiting", status_msg); + VLOG_INFO("pid %lu died, %s, exiting", + (unsigned long int) daemon_pid, s); + free(s); exit(0); } } @@ -459,11 +475,14 @@ daemonize_start(void) } /* If daemonization is configured, then this function notifies the parent - * process that the child process has completed startup successfully. */ + * process that the child process has completed startup successfully. + * + * Calling this function more than once has no additional effect. */ void daemonize_complete(void) { fork_notify_startup(daemonize_fd); + daemonize_fd = -1; if (detach) { setsid(); @@ -471,6 +490,7 @@ daemonize_complete(void) ignore(chdir("/")); } close_standard_fds(); + detach = false; } } @@ -484,7 +504,7 @@ daemon_usage(void) " --pidfile[=FILE] create pidfile (default: %s/%s.pid)\n" " --overwrite-pidfile with --pidfile, start even if already " "running\n", - ovs_rundir, program_name); + ovs_rundir(), program_name); } /* Opens and reads a PID from 'pidfile'. Returns the nonnegative PID if @@ -494,9 +514,21 @@ read_pidfile(const char *pidfile) { char line[128]; struct flock lck; + struct stat s; FILE *file; int error; + if ((pidfile_ino || pidfile_dev) + && !stat(pidfile, &s) + && s.st_ino == pidfile_ino && s.st_dev == pidfile_dev) { + /* It's our own pidfile. We can't afford to open it, because closing + * *any* fd for a file that a process has locked also releases all the + * locks on that file. + * + * Fortunately, we know the associated pid anyhow: */ + return getpid(); + } + file = fopen(pidfile, "r"); if (!file) { error = errno; @@ -508,6 +540,7 @@ read_pidfile(const char *pidfile) lck.l_whence = SEEK_SET; lck.l_start = 0; lck.l_len = 0; + lck.l_pid = 0; if (fcntl(fileno(file), F_GETLK, &lck)) { error = errno; VLOG_WARN("%s: fcntl: %s", pidfile, strerror(error));