]>
Commit | Line | Data |
---|---|---|
b40388bb MT |
1 | --- cyrus-imapd-2.1.3/lib/lock_flock.c Tue Oct 2 16:08:13 2001 |
2 | +++ cyrus-imapd-2.1.3-patched/lib/lock_flock.c Tue Apr 16 09:44:58 2002 | |
3 | @@ -51,6 +51,10 @@ | |
4 | #endif | |
5 | ||
6 | #include "lock.h" | |
7 | +#include <syslog.h> | |
8 | + | |
9 | +/* Locking timeout parameter */ | |
10 | +#define MAXTIME 99 | |
11 | ||
12 | const char *lock_method_desc = "flock"; | |
13 | ||
14 | @@ -69,6 +73,18 @@ | |
15 | * 'failaction' is provided, it is filled in with a pointer to a fixed | |
16 | * string naming the action that failed. | |
17 | * | |
18 | + * Modified by jwade 4/16/2002 to work around seen file locking problem | |
19 | + * Added locking timeout parameter to allow processes that are | |
20 | + * waiting for a lock to eventually time out | |
21 | + * | |
22 | + * Calls flock() in non-blocking fashion and then retries until a | |
23 | + * maximum delay is reached or the lock succeeds. | |
24 | + * | |
25 | + * As written, uses a quadratic backoff on retries with MAXTIME being | |
26 | + * the longest interval delay. Total delay time is the sum of the squares | |
27 | + * of all integers whose square is less than MAXTIME. In the case of | |
28 | + * MAXTIME = 99 this is 0+1+4+9+16+25+36+49+64+81= 285 Seconds | |
29 | + * This time is arbitrary and can be adjusted | |
30 | */ | |
31 | int lock_reopen(fd, filename, sbuf, failaction) | |
32 | int fd; | |
33 | @@ -79,17 +95,29 @@ | |
34 | int r; | |
35 | struct stat sbuffile, sbufspare; | |
36 | int newfd; | |
37 | + int delay=0, i=0; | |
38 | ||
39 | if (!sbuf) sbuf = &sbufspare; | |
40 | ||
41 | - for (;;) { | |
42 | - r = flock(fd, LOCK_EX); | |
43 | + for(i=0,delay=0;;) { | |
44 | + r = flock(fd, LOCK_EX|LOCK_NB); | |
45 | if (r == -1) { | |
46 | - if (errno == EINTR) continue; | |
47 | - if (failaction) *failaction = "locking"; | |
48 | + if (errno == EINTR) { | |
49 | + continue; | |
50 | + } | |
51 | + else if ((errno == EWOULDBLOCK) && (delay < MAXTIME)) { | |
52 | + syslog(LOG_DEBUG, "lock: reopen-blocked sleeping for %d on interval %d (%d, %s)" , delay, i, fd, filename); | |
53 | + sleep(delay); | |
54 | + i++; | |
55 | + delay = i*i; | |
56 | + continue; | |
57 | + } | |
58 | + if (failaction) { | |
59 | + if (delay >= MAXTIME) *failaction = "locking_timeout"; | |
60 | + else *failaction = "locking"; | |
61 | + } | |
62 | return -1; | |
63 | } | |
64 | - | |
65 | fstat(fd, sbuf); | |
66 | r = stat(filename, &sbuffile); | |
67 | if (r == -1) { | |
68 | @@ -97,9 +125,7 @@ | |
69 | flock(fd, LOCK_UN); | |
70 | return -1; | |
71 | } | |
72 | - | |
73 | if (sbuf->st_ino == sbuffile.st_ino) return 0; | |
74 | - | |
75 | newfd = open(filename, O_RDWR); | |
76 | if (newfd == -1) { | |
77 | if (failaction) *failaction = "opening"; |