dovecot: If we use notify I/O to watch for dotlock deletion, mak...

dovecot at dovecot.org dovecot at dovecot.org
Sat Dec 29 05:50:09 EET 2007


details:   http://hg.dovecot.org/dovecot/rev/622fa7cef9db
changeset: 7053:622fa7cef9db
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Dec 29 05:50:06 2007 +0200
description:
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.

diffstat:

1 file changed, 18 insertions(+), 11 deletions(-)
src/lib/file-dotlock.c |   29 ++++++++++++++++++-----------

diffs (53 lines):

diff -r c751ec28b869 -r 622fa7cef9db src/lib/file-dotlock.c
--- 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
@@ -175,6 +175,22 @@ static int update_lock_info(time_t now, 
 	*changed_r = update_change_info(&st, &lock_info->lock_info,
 					&lock_info->last_change, now,
 					!lock_info->set->nfs_flush);
+	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;
 }
 
@@ -230,12 +246,7 @@ static int check_lock(time_t now, struct
 
 		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 @@ static int check_lock(time_t now, struct
 
 	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;


More information about the dovecot-cvs mailing list