From 18e124a20b366ee96e73600624a1a4000c816604 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 29 Mar 2011 09:44:55 -0700 Subject: [PATCH] daemon: Avoid redundant code in already_running(). This function substantially duplicated read_pidfile(), so reuse that code instead. --- lib/daemon.c | 59 ++++++++++++++++++++++---------------------- lib/daemon.h | 1 + python/ovs/daemon.py | 48 ++++++++++++++--------------------- 3 files changed, 48 insertions(+), 60 deletions(-) diff --git a/lib/daemon.c b/lib/daemon.c index 17ec9f5e..cb440d16 100644 --- a/lib/daemon.c +++ b/lib/daemon.c @@ -139,37 +139,17 @@ daemon_set_monitor(void) monitor = true; } -/* If a pidfile has been configured and that pidfile already exists and is - * locked by a running process, returns the pid of the running process. - * Otherwise, returns 0. */ -static pid_t -already_running(void) -{ - pid_t pid = 0; - if (pidfile) { - int fd = open(pidfile, O_RDWR); - if (fd >= 0) { - struct flock lck; - lck.l_type = F_WRLCK; - lck.l_whence = SEEK_SET; - lck.l_start = 0; - lck.l_len = 0; - if (fcntl(fd, F_GETLK, &lck) != -1 && lck.l_type != F_UNLCK) { - pid = lck.l_pid; - } - close(fd); - } - } - return pid; -} - /* If a locked pidfile exists, issue a warning message and, unless * ignore_existing_pidfile() has been called, terminate the program. */ void die_if_already_running(void) { - pid_t pid = already_running(); - if (pid) { + pid_t pid; + if (!pidfile) { + return; + } + pid = read_pidfile_if_exists(pidfile); + if (pid > 0) { if (!overwrite_pidfile) { VLOG_ERR("%s: %s already running as pid %ld, aborting", get_pidfile(), program_name, (long int) pid); @@ -509,10 +489,8 @@ daemon_usage(void) ovs_rundir(), program_name); } -/* Opens and reads a PID from 'pidfile'. Returns the nonnegative PID if - * successful, otherwise a negative errno value. */ -pid_t -read_pidfile(const char *pidfile) +static pid_t +read_pidfile__(const char *pidfile, bool must_exist) { char line[128]; struct flock lck; @@ -533,6 +511,9 @@ read_pidfile(const char *pidfile) file = fopen(pidfile, "r"); if (!file) { + if (errno == ENOENT && !must_exist) { + return 0; + } error = errno; VLOG_WARN("%s: open: %s", pidfile, strerror(error)); goto error; @@ -581,3 +562,21 @@ error: } return -error; } + +/* Opens and reads a PID from 'pidfile'. Returns the positive PID if + * successful, otherwise a negative errno value. */ +pid_t +read_pidfile(const char *pidfile) +{ + return read_pidfile__(pidfile, true); +} + + +/* Opens and reads a PID from 'pidfile', if it exists. Returns 0 if 'pidfile' + * doesn't exist, the positive PID if successful, otherwise a negative errno + * value. */ +pid_t +read_pidfile_if_exists(const char *pidfile) +{ + return read_pidfile__(pidfile, false); +} diff --git a/lib/daemon.h b/lib/daemon.h index dd85b463..8f4fe390 100644 --- a/lib/daemon.h +++ b/lib/daemon.h @@ -71,5 +71,6 @@ void die_if_already_running(void); void ignore_existing_pidfile(void); void daemon_usage(void); pid_t read_pidfile(const char *name); +pid_t read_pidfile_if_exists(const char *name); #endif /* daemon.h */ diff --git a/python/ovs/daemon.py b/python/ovs/daemon.py index 83ae8cd1..4e54e697 100644 --- a/python/ovs/daemon.py +++ b/python/ovs/daemon.py @@ -111,37 +111,15 @@ def set_monitor(): global _monitor _monitor = True -def _already_running(): - """If a pidfile has been configured and that pidfile already exists and is - locked by a running process, returns True. Otherwise, returns False.""" - if _pidfile is not None: - try: - file = open(_pidfile, "r+") - try: - try: - fcntl.lockf(file, fcntl.LOCK_EX | fcntl.LOCK_NB) - except IOError, e: - if e.errno in [errno.EACCES, errno.EAGAIN]: - return True - logging.error("error locking %s (%s)" - % (_pidfile, os.strerror(e.errno))) - return False - finally: - # This releases the lock, which we don't really want. - file.close() - except IOError, e: - if e.errno == errno.ENOENT: - return False - logging.error("error opening %s (%s)" - % (_pidfile, os.strerror(e.errno))) - return False - def die_if_already_running(): """If a locked pidfile exists, issue a warning message and, unless ignore_existing_pidfile() has been called, terminate the program.""" - if _already_running(): + if _pidfile is None: + return + pid = read_pidfile_if_exists(_pidfile) + if pid > 0: if not _overwrite_pidfile: - msg = "%s: already running" % _pidfile + msg = "%s: already running as pid %d" % (_pidfile, pid) logging.error("%s, aborting" % msg) sys.stderr.write("%s\n" % msg) sys.exit(1) @@ -382,9 +360,7 @@ Daemon options: --overwrite-pidfile with --pidfile, start even if already running """ % (ovs.dirs.RUNDIR, ovs.util.PROGRAM_NAME)) -def read_pidfile(pidfile): - """Opens and reads a PID from 'pidfile'. Returns the nonnegative PID if - successful, otherwise a negative errno value.""" +def __read_pidfile(pidfile, must_exist): if _pidfile_dev is not None: try: s = os.stat(pidfile) @@ -401,6 +377,8 @@ def read_pidfile(pidfile): try: file = open(pidfile, "r") except IOError, e: + if e.errno == errno.ENOENT and not must_exist: + return 0 logging.warning("%s: open: %s" % (pidfile, os.strerror(e.errno))) return -e.errno @@ -437,6 +415,16 @@ def read_pidfile(pidfile): except IOError: pass +def read_pidfile(pidfile): + """Opens and reads a PID from 'pidfile'. Returns the positive PID if + successful, otherwise a negative errno value.""" + return __read_pidfile(pidfile, True) + +def read_pidfile_if_exists(pidfile): + """Opens and reads a PID from 'pidfile'. Returns 0 if 'pidfile' does not + exist, the positive PID if successful, otherwise a negative errno value.""" + return __read_pidfile(pidfile, False) + # XXX Python's getopt does not support options with optional arguments, so we # have to separate --pidfile (with no argument) from --pidfile-name (with an # argument). Need to write our own getopt I guess. -- 2.30.2