changeset 7053:622fa7cef9db HEAD

If we use notify I/O to watch for dotlock deletion, make sure we still sleep a while after overriding a dotlock. Otherwise multiple processes might try to do that at the same time and unlink each others' newly created dotlocks.
author Timo Sirainen <tss@iki.fi>
date Sat, 29 Dec 2007 05:50:06 +0200
parents c751ec28b869
children 4c6e9edfd4ce
files src/lib/file-dotlock.c
diffstat 1 files changed, 18 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/file-dotlock.c	Sat Dec 29 05:37:27 2007 +0200
+++ b/src/lib/file-dotlock.c	Sat Dec 29 05:50:06 2007 +0200
@@ -178,6 +178,22 @@
 	return 0;
 }
 
+static int dotlock_override(struct lock_info *lock_info)
+{
+	if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
+		i_error("unlink(%s) failed: %m",
+			lock_info->lock_path);
+		return -1;
+	}
+
+	/* make sure we sleep for a while after overriding the lock file.
+	   otherwise another process might try to override it at the same time
+	   and unlink our newly created dotlock. */
+	if (lock_info->use_io_notify)
+		usleep(LOCK_RANDOM_USLEEP_TIME);
+	return 0;
+}
+
 static int check_lock(time_t now, struct lock_info *lock_info)
 {
 	time_t stale_timeout = lock_info->set->stale_timeout;
@@ -230,12 +246,7 @@
 
 		if (!changed) {
 			/* still there, go ahead and override it */
-			if (unlink(lock_info->lock_path) < 0 &&
-			    errno != ENOENT) {
-				i_error("unlink(%s) failed: %m",
-					lock_info->lock_path);
-				return -1;
-			}
+			return dotlock_override(lock_info);
 		}
 		return 1;
 	}
@@ -271,11 +282,7 @@
 
 	if (now > lock_info->last_change + stale_timeout) {
 		/* no changes for a while, assume stale lock */
-		if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
-			i_error("unlink(%s) failed: %m", lock_info->lock_path);
-			return -1;
-		}
-		return 1;
+		return dotlock_override(lock_info);
 	}
 
 	return 0;