# HG changeset patch # User Timo Sirainen # Date 1198900206 -7200 # Node ID 622fa7cef9db802a3e9802f68115bba60de34931 # Parent c751ec28b869a0a10dfac06541c9fb2a7f8958b8 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. 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 @@ -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;