diff -up cyrus-imapd-2.4.6/lib/lock_flock.c.flock cyrus-imapd-2.4.6/lib/lock_flock.c --- cyrus-imapd-2.4.6/lib/lock_flock.c.flock 2010-12-20 14:15:49.000000000 +0100 +++ cyrus-imapd-2.4.6/lib/lock_flock.c 2011-02-10 12:56:45.262786102 +0100 @@ -52,6 +52,10 @@ #endif #include "cyr_lock.h" +#include + +/* Locking timeout parameter */ +#define MAXTIME 99 const char *lock_method_desc = "flock"; @@ -68,6 +72,18 @@ const char *lock_method_desc = "flock"; * 'failaction' is provided, it is filled in with a pointer to a fixed * string naming the action that failed. * + * Modified by jwade 4/16/2002 to work around seen file locking problem + * Added locking timeout parameter to allow processes that are + * waiting for a lock to eventually time out + * + * Calls flock() in non-blocking fashion and then retries until a + * maximum delay is reached or the lock succeeds. + * + * As written, uses a quadratic backoff on retries with MAXTIME being + * the longest interval delay. Total delay time is the sum of the squares + * of all integers whose square is less than MAXTIME. In the case of + * MAXTIME = 99 this is 0+1+4+9+16+25+36+49+64+81= 285 Seconds + * This time is arbitrary and can be adjusted */ int lock_reopen(fd, filename, sbuf, failaction) int fd; @@ -78,17 +94,29 @@ const char **failaction; int r; struct stat sbuffile, sbufspare; int newfd; + int delay=0, i=0; if (!sbuf) sbuf = &sbufspare; - for (;;) { - r = flock(fd, LOCK_EX); + for(i=0,delay=0;;) { + r = flock(fd, LOCK_EX|LOCK_NB); if (r == -1) { - if (errno == EINTR) continue; - if (failaction) *failaction = "locking"; + if (errno == EINTR) { + continue; + } + else if ((errno == EWOULDBLOCK) && (delay < MAXTIME)) { + syslog(LOG_DEBUG, "lock: reopen-blocked sleeping for %d on interval %d (%d, %s)" , delay, i, fd, filename); + sleep(delay); + i++; + delay = i*i; + continue; + } + if (failaction) { + if (delay >= MAXTIME) *failaction = "locking_timeout"; + else *failaction = "locking"; + } return -1; } - fstat(fd, sbuf); r = stat(filename, &sbuffile); if (r == -1) { @@ -96,9 +124,7 @@ const char **failaction; flock(fd, LOCK_UN); return -1; } - if (sbuf->st_ino == sbuffile.st_ino) return 0; - newfd = open(filename, O_RDWR); if (newfd == -1) { if (failaction) *failaction = "opening";