daemon: Avoid redundant code in already_running().
authorBen Pfaff <blp@nicira.com>
Tue, 29 Mar 2011 16:44:55 +0000 (09:44 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 29 Mar 2011 17:09:47 +0000 (10:09 -0700)
This function substantially duplicated read_pidfile(), so reuse that
code instead.

lib/daemon.c
lib/daemon.h
python/ovs/daemon.py

index 17ec9f5..cb440d1 100644 (file)
@@ -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);
+}
index dd85b46..8f4fe39 100644 (file)
@@ -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 */
index 83ae8cd..4e54e69 100644 (file)
@@ -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.