Группа :: Система/Серверы
Пакет: cyrus-imapd
Главная Изменения Спек Патчи Загрузить Bugs and FR
Патч: cyrus-imapd-2.1.3-flock.patch
--- cyrus-imapd-2.1.3/lib/lock_flock.c Tue Oct 2 16:08:13 2001
+++ cyrus-imapd-2.1.3-patched/lib/lock_flock.c Tue Apr 16 09:44:58 2002
@@ -51,6 +51,10 @@
#endif
#include "lock.h"
+#include <syslog.h>
+
+/* Locking timeout parameter */
+#define MAXTIME 99
const char *lock_method_desc = "flock";
@@ -69,6 +73,18 @@
* '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;
@@ -79,17 +95,29 @@
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) {
@@ -97,9 +125,7 @@
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";