lockfile: Log more helpful message when locking fails due to a conflict.
authorBen Pfaff <blp@nicira.com>
Fri, 31 Aug 2012 17:11:15 +0000 (10:11 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 31 Aug 2012 17:11:15 +0000 (10:11 -0700)
Reported-by: rahim entezari <rahim.entezari@gmail.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Ethan Jackson <ethan@nicira.com>
AUTHORS
lib/lockfile.c
tests/lockfile.at

diff --git a/AUTHORS b/AUTHORS
index 28dc742f39bc5216662ee9d7a6b2f947663aef5e..2389b5a0836db0f92c9bf5e4dcbf7dad8b9c1dfc 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -175,6 +175,7 @@ YAMAMOTO Takashi        yamamoto@valinux.co.jp
 Yongqiang Liu           liuyq7809@gmail.com
 kk yap                  yapkke@stanford.edu
 likunyun                kunyunli@hotmail.com
+rahim entezari          rahim.entezari@gmail.com
 冯全树(Crab)            fqs888@126.com
 胡靖飞                  hujingfei914@msn.com
 
index db84aebb40cec38dd0bc590b22109104a0556eac..3708aec0d8ec58f887a542905f0780bc927ca203 100644 (file)
@@ -55,7 +55,8 @@ struct lockfile {
 static struct hmap lock_table = HMAP_INITIALIZER(&lock_table);
 
 static void lockfile_unhash(struct lockfile *);
-static int lockfile_try_lock(const char *name, struct lockfile **lockfilep);
+static int lockfile_try_lock(const char *name, pid_t *pidp,
+                             struct lockfile **lockfilep);
 
 /* Returns the name of the lockfile that would be created for locking a file
  * named 'filename_'.  The caller is responsible for freeing the returned name,
@@ -98,21 +99,27 @@ lockfile_lock(const char *file, struct lockfile **lockfilep)
      * stylized ways such that any number of readers may access a file while it
      * is being written. */
     char *lock_name;
+    pid_t pid;
     int error;
 
     COVERAGE_INC(lockfile_lock);
 
     lock_name = lockfile_name(file);
 
-    error = lockfile_try_lock(lock_name, lockfilep);
+    error = lockfile_try_lock(lock_name, &pid, lockfilep);
 
     if (error) {
         COVERAGE_INC(lockfile_error);
         if (error == EACCES) {
             error = EAGAIN;
         }
-        VLOG_WARN("%s: failed to lock file: %s",
-                  lock_name, strerror(error));
+        if (pid) {
+            VLOG_WARN("%s: cannot lock file because it is already locked by "
+                      "pid %ld", lock_name, (long int) pid);
+        } else {
+            VLOG_WARN("%s: failed to lock file: %s",
+                      lock_name, strerror(error));
+        }
     }
 
     free(lock_name);
@@ -201,7 +208,7 @@ lockfile_register(const char *name, dev_t device, ino_t inode, int fd)
 }
 
 static int
-lockfile_try_lock(const char *name, struct lockfile **lockfilep)
+lockfile_try_lock(const char *name, pid_t *pidp, struct lockfile **lockfilep)
 {
     struct flock l;
     struct stat s;
@@ -209,6 +216,7 @@ lockfile_try_lock(const char *name, struct lockfile **lockfilep)
     int fd;
 
     *lockfilep = NULL;
+    *pidp = 0;
 
     /* Check whether we've already got a lock on that file. */
     if (!stat(name, &s)) {
@@ -250,6 +258,9 @@ lockfile_try_lock(const char *name, struct lockfile **lockfilep)
     if (!error) {
         *lockfilep = lockfile_register(name, s.st_dev, s.st_ino, fd);
     } else {
+        if (!fcntl(fd, F_GETLK, &l) && l.l_type != F_UNLCK) {
+            *pidp = l.l_pid;
+        }
         close(fd);
     }
     return error;
index 50999e47e1f372416afb525aeb270fa1e80c1ab0..2644d3fa0f750e05171ebad0b9a2951247c94287 100644 (file)
@@ -5,7 +5,8 @@ m4_define([CHECK_LOCKFILE],
    AT_KEYWORDS([lockfile])
    AT_CHECK([test-lockfile $1], [0], [$1: success (m4_if(
      [$2], [1], [$2 child], [$2 children]))
-], [$3])
+], [stderr])
+   AT_CHECK([sed 's/pid [[0-9]]*/pid <pid>/' stderr], [0], [$3])
    AT_CLEANUP])
 
 CHECK_LOCKFILE([lock_and_unlock], [0])
@@ -23,13 +24,13 @@ lockfile|WARN|.file.~lock~: failed to lock file: Resource deadlock avoided
 
 CHECK_LOCKFILE([lock_blocks_other_process], [1],
   [lockfile|WARN|.file.~lock~: child does not inherit lock
-lockfile|WARN|.file.~lock~: failed to lock file: Resource temporarily unavailable
+lockfile|WARN|.file.~lock~: cannot lock file because it is already locked by pid <pid>
 ])
 
 CHECK_LOCKFILE([lock_twice_blocks_other_process], [1],
   [lockfile|WARN|.file.~lock~: failed to lock file: Resource deadlock avoided
 lockfile|WARN|.file.~lock~: child does not inherit lock
-lockfile|WARN|.file.~lock~: failed to lock file: Resource temporarily unavailable
+lockfile|WARN|.file.~lock~: cannot lock file because it is already locked by pid <pid>
 ])
 
 CHECK_LOCKFILE([lock_and_unlock_allows_other_process], [1])