1 # HG changeset patch |
1 # HG changeset patch |
2 # Parent 5037ac63d7aece4b5e96e26bace1ab4b7e791804 |
2 # Parent d54ee7005f7f7b5970ce45caf7487a9fd929e55f |
3 |
3 |
4 diff -r 5037ac63d7ae Local/Makefile |
4 diff -r d54ee7005f7f Local/Makefile |
5 --- a/Local/Makefile Sat Feb 19 13:42:16 2011 +0100 |
5 --- a/Local/Makefile Mon Feb 21 22:52:42 2011 +0100 |
6 +++ b/Local/Makefile Sun Feb 20 23:37:25 2011 +0100 |
6 +++ b/Local/Makefile Wed Feb 23 00:53:29 2011 +0100 |
7 @@ -1,4 +1,5 @@ |
7 @@ -1,4 +1,5 @@ |
8 # $Cambridge: exim/src/src/EDITME,v 1.27 2010/06/12 15:21:25 jetmore Exp $ |
8 # $Cambridge: exim/src/src/EDITME,v 1.27 2010/06/12 15:21:25 jetmore Exp $ |
9 +EXTRALIBS_EXIM=-lrt |
9 +EXTRALIBS_EXIM=-lrt |
10 |
10 |
11 ################################################## |
11 ################################################## |
12 # The Exim mail transport agent # |
12 # The Exim mail transport agent # |
13 diff -r 5037ac63d7ae src/transports/appendfile.c |
13 diff -r d54ee7005f7f src/transports/appendfile.c |
14 --- a/src/transports/appendfile.c Sat Feb 19 13:42:16 2011 +0100 |
14 --- a/src/transports/appendfile.c Mon Feb 21 22:52:42 2011 +0100 |
15 +++ b/src/transports/appendfile.c Sun Feb 20 23:37:25 2011 +0100 |
15 +++ b/src/transports/appendfile.c Wed Feb 23 00:53:29 2011 +0100 |
16 @@ -13,6 +13,7 @@ |
16 @@ -13,6 +13,7 @@ |
17 |
17 |
18 #ifdef SUPPORT_MAILDIR |
18 #ifdef SUPPORT_MAILDIR |
19 #include "tf_maildir.h" |
19 #include "tf_maildir.h" |
20 +extern int lockfd; /* from tf_maildir */ // hs12 |
20 +extern int lockfd; /* from tf_maildir */ // hs12 |
21 #endif |
21 #endif |
22 |
22 |
23 |
23 |
24 @@ -278,8 +279,8 @@ |
24 @@ -239,6 +240,30 @@ |
|
25 TRUE /* quota_is_inclusive */ |
|
26 }; |
|
27 |
|
28 +void hs12_lock(int fd, int type, const char* msg) |
|
29 +{ |
|
30 + struct timespec t0, t1; |
|
31 + clock_gettime(CLOCK_REALTIME, &t0); |
|
32 + const char *ltype = |
|
33 + type == F_UNLCK ? "UNLOCK" |
|
34 + : type == F_RDLCK ? "READ LOCK" |
|
35 + : "WRITE LOCK"; |
|
36 + |
|
37 + DEBUG(D_transport) debug_printf("%s: %s\n", ltype, msg); |
|
38 + |
|
39 + |
|
40 + (void)apply_lock(fd, type, 1, 120, 0, 0); |
|
41 + if (type == F_UNLCK) return; |
|
42 + |
|
43 + clock_gettime(CLOCK_REALTIME, &t1); |
|
44 + t1.tv_sec -= t0.tv_sec; |
|
45 + t1.tv_nsec -= t0.tv_nsec; |
|
46 + if (t1.tv_nsec < 0) { t1.tv_sec--; t1.tv_nsec *= -1; } |
|
47 + DEBUG(D_transport) |
|
48 + debug_printf("%s: %s was waiting for %d.%09d seconds\n", |
|
49 + ltype, msg, t1.tv_sec, t1.tv_nsec); |
|
50 + return; |
|
51 +} |
|
52 |
|
53 |
|
54 /************************************************* |
|
55 @@ -278,8 +303,8 @@ |
25 gid = gid; |
56 gid = gid; |
26 |
57 |
27 if (ob->expand_maildir_use_size_file) |
58 if (ob->expand_maildir_use_size_file) |
28 - ob->maildir_use_size_file = expand_check_condition(ob->expand_maildir_use_size_file, |
59 - ob->maildir_use_size_file = expand_check_condition(ob->expand_maildir_use_size_file, |
29 - US"`maildir_use_size_file` in transport", tblock->name); |
60 - US"`maildir_use_size_file` in transport", tblock->name); |
30 + ob->maildir_use_size_file = expand_check_condition(ob->expand_maildir_use_size_file, |
61 + ob->maildir_use_size_file = expand_check_condition(ob->expand_maildir_use_size_file, |
31 + US"`maildir_use_size_file` in transport", tblock->name); |
62 + US"`maildir_use_size_file` in transport", tblock->name); |
32 |
63 |
33 /* Loop for quota, quota_filecount, quota_warn_threshold, mailbox_size, |
64 /* Loop for quota, quota_filecount, quota_warn_threshold, mailbox_size, |
34 mailbox_filecount */ |
65 mailbox_filecount */ |
35 @@ -841,7 +842,7 @@ |
66 @@ -841,7 +866,7 @@ |
36 sigalrm_seen set if there has been a timeout |
67 sigalrm_seen set if there has been a timeout |
37 */ |
68 */ |
38 |
69 |
39 -static int |
70 -static int |
40 +int |
71 +int |
41 apply_lock(int fd, int fcntltype, BOOL dofcntl, int fcntltime, BOOL doflock, |
72 apply_lock(int fd, int fcntltype, BOOL dofcntl, int fcntltime, BOOL doflock, |
42 int flocktime) |
73 int flocktime) |
43 { |
74 { |
44 @@ -887,7 +888,6 @@ |
75 @@ -887,7 +912,6 @@ |
45 |
76 |
46 |
77 |
47 |
78 |
48 - |
79 - |
49 #ifdef SUPPORT_MBX |
80 #ifdef SUPPORT_MBX |
50 /************************************************* |
81 /************************************************* |
51 * Copy message into MBX mailbox * |
82 * Copy message into MBX mailbox * |
52 @@ -2416,18 +2416,32 @@ |
83 @@ -2416,18 +2440,19 @@ |
53 { |
84 { |
54 off_t size; |
85 off_t size; |
55 int filecount; |
86 int filecount; |
56 + uschar *excuse; |
87 + uschar *excuse; |
57 + |
|
58 + struct timespec t0, t1; |
|
59 + clock_gettime(CLOCK_REALTIME, &t0); |
|
60 |
88 |
61 maildirsize_fd = maildir_ensure_sizefile(check_path, ob, regex, dir_regex, |
89 maildirsize_fd = maildir_ensure_sizefile(check_path, ob, regex, dir_regex, |
62 - &size, &filecount); |
90 - &size, &filecount); |
63 + &size, &filecount, &excuse); |
91 + &size, &filecount, &excuse); |
64 |
92 |
65 if (maildirsize_fd == -1) |
93 if (maildirsize_fd == -1) |
66 { |
94 { |
67 addr->basic_errno = errno; |
95 addr->basic_errno = errno; |
68 - addr->message = string_sprintf("while opening or reading " |
96 - addr->message = string_sprintf("while opening or reading " |
69 - "%s/maildirsize", check_path); |
97 - "%s/maildirsize", check_path); |
70 + //addr->message = string_sprintf("%s", excuse); |
|
71 + addr->message = excuse; |
98 + addr->message = excuse; |
72 return FALSE; |
99 return FALSE; |
73 } |
100 } |
74 |
101 |
75 + |
102 + |
76 + clock_gettime(CLOCK_REALTIME, &t1); |
|
77 + t1.tv_sec -= t0.tv_sec; |
|
78 + t1.tv_nsec -= t0.tv_nsec; |
|
79 + if (t1.tv_nsec < 0) { t1.tv_sec--; t1.tv_nsec *= -1; } |
|
80 + DEBUG(D_transport) { |
|
81 + if (t1.tv_sec >= 1) debug_printf("%s/maildirsize was locked for %d.09ld seconds\n", |
|
82 + check_path, t1.tv_sec, t1.tv_nsec); |
|
83 + } |
|
84 + |
|
85 if (mailbox_size < 0) mailbox_size = size; |
103 if (mailbox_size < 0) mailbox_size = size; |
86 if (mailbox_filecount < 0) mailbox_filecount = filecount; |
104 if (mailbox_filecount < 0) mailbox_filecount = filecount; |
87 } |
105 } |
88 @@ -3125,6 +3139,8 @@ |
106 @@ -3125,6 +3150,8 @@ |
89 uschar *renamename = newname; |
107 uschar *renamename = newname; |
90 fd = -1; |
108 fd = -1; |
91 |
109 |
92 + if (lockfd >= 0) (void)apply_lock(lockfd, F_RDLCK, 1, 120, 0, 0); // hs12 |
110 + if (lockfd >= 0) hs12_lock(lockfd, F_RDLCK, "delivery"); |
93 + |
111 + |
94 DEBUG(D_transport) debug_printf("renaming temporary file\n"); |
112 DEBUG(D_transport) debug_printf("renaming temporary file\n"); |
95 |
113 |
96 /* If there is no rename name set, we are in a non-maildir, non-mailstore |
114 /* If there is no rename name set, we are in a non-maildir, non-mailstore |
97 @@ -3245,6 +3261,7 @@ |
115 @@ -3245,6 +3272,7 @@ |
98 filename = dataname = NULL; /* Prevents attempt to unlink at end */ |
116 filename = dataname = NULL; /* Prevents attempt to unlink at end */ |
99 } |
117 } |
100 } /* maildir or mailstore */ |
118 } /* maildir or mailstore */ |
101 + |
119 + |
102 } /* successful write + close */ |
120 } /* successful write + close */ |
103 } /* isdirectory */ |
121 } /* isdirectory */ |
104 } /* write success */ |
122 } /* write success */ |
105 @@ -3280,6 +3297,11 @@ |
123 @@ -3280,6 +3308,11 @@ |
106 detected, in order to get the file closed and the lock file tidied away. */ |
124 detected, in order to get the file closed and the lock file tidied away. */ |
107 |
125 |
108 RETURN: |
126 RETURN: |
109 +if (lockfd >= 0) |
127 +if (lockfd >= 0) |
110 + { |
128 + { |
111 + (void)apply_lock(lockfd, F_UNLCK, 1, 120, 0, 0); // hs12 |
129 + hs12_lock(lockfd, F_UNLCK, "done delivery"); |
112 + (void)close(lockfd); |
130 + (void)close(lockfd); |
113 + } |
131 + } |
114 |
132 |
115 #ifdef SUPPORT_MBX |
133 #ifdef SUPPORT_MBX |
116 if (mbx_lockfd >= 0) |
134 if (mbx_lockfd >= 0) |
117 diff -r 5037ac63d7ae src/transports/appendfile.h |
135 diff -r d54ee7005f7f src/transports/appendfile.h |
118 --- a/src/transports/appendfile.h Sat Feb 19 13:42:16 2011 +0100 |
136 --- a/src/transports/appendfile.h Mon Feb 21 22:52:42 2011 +0100 |
119 +++ b/src/transports/appendfile.h Sun Feb 20 23:37:25 2011 +0100 |
137 +++ b/src/transports/appendfile.h Wed Feb 23 00:53:29 2011 +0100 |
120 @@ -95,5 +95,8 @@ |
138 @@ -95,5 +95,8 @@ |
121 /* Function that is shared with tf_maildir.c */ |
139 /* Function that is shared with tf_maildir.c */ |
122 |
140 |
123 extern off_t check_dir_size(uschar *, int *, const pcre *); |
141 extern off_t check_dir_size(uschar *, int *, const pcre *); |
124 +extern int apply_lock(int fd, int fcntltype, BOOL dofcntl, int fcntltime, BOOL doflock, |
142 +extern int apply_lock(int fd, int fcntltype, BOOL dofcntl, int fcntltime, BOOL doflock, |
125 + int flocktime); |
143 + int flocktime); |
126 + |
144 + |
127 |
145 |
128 /* End of transports/appendfile.h */ |
146 /* End of transports/appendfile.h */ |
129 diff -r 5037ac63d7ae src/transports/tf_maildir.c |
147 diff -r d54ee7005f7f src/transports/tf_maildir.c |
130 --- a/src/transports/tf_maildir.c Sat Feb 19 13:42:16 2011 +0100 |
148 --- a/src/transports/tf_maildir.c Mon Feb 21 22:52:42 2011 +0100 |
131 +++ b/src/transports/tf_maildir.c Sun Feb 20 23:37:25 2011 +0100 |
149 +++ b/src/transports/tf_maildir.c Wed Feb 23 00:53:29 2011 +0100 |
132 @@ -367,13 +367,16 @@ |
150 @@ -367,13 +367,16 @@ |
133 |
151 |
134 Returns: >=0 a file descriptor for an open maildirsize file |
152 Returns: >=0 a file descriptor for an open maildirsize file |
135 -1 there was an error opening or accessing the file |
153 -1 there was an error opening or accessing the file |
136 + or locking |
154 + or locking |
145 - int *returned_filecount) |
163 - int *returned_filecount) |
146 + int *returned_filecount, uschar **excuse) |
164 + int *returned_filecount, uschar **excuse) |
147 { |
165 { |
148 int count, fd; |
166 int count, fd; |
149 off_t cached_quota = 0; |
167 off_t cached_quota = 0; |
150 @@ -381,25 +384,80 @@ |
168 @@ -381,25 +384,48 @@ |
151 int filecount = 0; |
169 int filecount = 0; |
152 int linecount = 0; |
170 int linecount = 0; |
153 off_t size = 0; |
171 off_t size = 0; |
154 -uschar *filename; |
172 -uschar *filename; |
155 +uschar *filename, *lockname, *hitchname; |
173 +uschar *filename, *lockname, *hitchname; |
156 uschar buffer[MAX_FILE_SIZE]; |
174 uschar buffer[MAX_FILE_SIZE]; |
157 uschar *ptr = buffer; |
175 uschar *ptr = buffer; |
158 uschar *endptr; |
176 uschar *endptr; |
159 |
177 |
|
178 -/* Try a few times to open or create the file, in case another process is doing |
|
179 -the same thing. */ |
160 +filename = string_sprintf("%s/maildirsize", path); |
180 +filename = string_sprintf("%s/maildirsize", path); |
161 +lockname = string_sprintf("%s.lock", filename); |
181 +lockname = string_sprintf("%s.lock", filename); |
162 +hitchname = string_sprintf( "%s.%s.%08x.%08x", lockname, primary_hostname, |
182 +hitchname = string_sprintf( "%s.%s.%08x.%08x", lockname, primary_hostname, |
163 + (unsigned int)(time(NULL)), (unsigned int)getpid()); |
183 + (unsigned int)(time(NULL)), (unsigned int)getpid()); |
164 + |
184 |
|
185 -filename = string_sprintf("%s/maildirsize", path); |
165 +/* Try to create a lock file. Here we should copy the loop from appendfile.c, |
186 +/* Try to create a lock file. Here we should copy the loop from appendfile.c, |
166 +since our approach is quite simplified */ |
187 +since our approach is quite simplified */ |
167 +lockfd = Uopen(lockname, O_CREAT|O_RDWR, ob->mode ? ob->mode : 0600); |
188 +lockfd = Uopen(lockname, O_CREAT|O_RDWR, ob->mode ? ob->mode : 0600); |
168 +if (lockfd < 0) |
189 +if (lockfd < 0) |
169 + { |
|
170 + if (errno != ENOENT) |
|
171 + { |
190 + { |
172 + *excuse = string_sprintf("open %s", lockname); |
191 + *excuse = string_sprintf("open %s", lockname); |
173 + return -1; |
192 + return -1; |
174 + } |
193 + } |
175 + |
194 + |
176 + lockfd = Uopen(hitchname, O_WRONLY|O_CREAT|O_EXCL, ob->mode ? ob->mode : 0600); |
|
177 + if (lockfd < 0) |
|
178 + { |
|
179 + *excuse = string_sprintf("open %s", hitchname); |
|
180 + return -1; |
|
181 + } |
|
182 + if (link(hitchname, lockname) < 0) |
|
183 + { |
|
184 + int save_errno = errno; |
|
185 + (void)unlink(hitchname); |
|
186 + errno = save_errno; |
|
187 + if (errno != EEXIST) |
|
188 + { |
|
189 + *excuse = string_sprintf("link %s -> %s", hitchname, lockname); |
|
190 + return -1; |
|
191 + } |
|
192 + (void)close(lockfd); |
|
193 + lockfd = Uopen(lockname, O_WRONLY, ob->mode ? ob->mode : 0600); |
|
194 + if (lockfd < 0) |
|
195 + { |
|
196 + *excuse = string_sprintf("open %s", lockname); |
|
197 + return -1; |
|
198 + } |
|
199 + } |
|
200 + (void)unlink(hitchname); |
|
201 + } |
|
202 + |
|
203 + |
|
204 +/* Before doing anything here we try to open and lock the maildirsize.lock |
195 +/* Before doing anything here we try to open and lock the maildirsize.lock |
205 +file. This should prevent/avoid races and parallel recalculations. We |
196 +file. This should prevent/avoid races and parallel recalculations. We |
206 +need to do this on an extra lockfile, since the maildirsize file itself |
197 +need to do this on an extra lockfile, since the maildirsize file itself |
207 +gets renamed during the recalculation. */ |
198 +gets renamed during the recalculation. */ |
208 + |
199 + |
209 +if (lockfd >= 0) |
200 +hs12_lock(lockfd, F_WRLCK, "checking"); |
210 +(void)apply_lock(lockfd, F_WRLCK, 1, 120, 0, 0); // hs12 |
|
211 +if (sigalrm_seen) |
201 +if (sigalrm_seen) |
212 + { |
202 + { |
213 + *excuse = string_sprintf("timeout locking %s", lockname); |
203 + *excuse = string_sprintf("timeout locking %s", lockname); |
214 + return -1; |
204 + return -1; |
215 + } |
205 + } |
216 +DEBUG(D_transport) debug_printf("locked (WR) %s\n", lockname); |
206 + |
217 + |
207 |
218 /* Try a few times to open or create the file, in case another process is doing |
|
219 the same thing. */ |
|
220 |
|
221 -filename = string_sprintf("%s/maildirsize", path); |
|
222 - |
|
223 DEBUG(D_transport) debug_printf("looking for maildirsize in %s\n", path); |
208 DEBUG(D_transport) debug_printf("looking for maildirsize in %s\n", path); |
224 fd = Uopen(filename, O_RDWR|O_APPEND, ob->mode ? ob->mode : 0600); |
209 fd = Uopen(filename, O_RDWR|O_APPEND, ob->mode ? ob->mode : 0600); |
225 -if (fd < 0) |
210 -if (fd < 0) |
226 - { |
211 - { |
227 +if (fd < 0) { |
212 +if (fd < 0) { |
229 DEBUG(D_transport) |
214 DEBUG(D_transport) |
230 debug_printf("%s does not exist: recalculating\n", filename); |
215 debug_printf("%s does not exist: recalculating\n", filename); |
231 goto RECALCULATE; |
216 goto RECALCULATE; |
232 - } |
217 - } |
233 +} |
218 +} |
|
219 +(void)lseek(fd, 0, SEEK_SET); |
|
220 + |
234 |
221 |
235 /* The file has been successfully opened. Check that the cached quota value is |
222 /* The file has been successfully opened. Check that the cached quota value is |
236 still correct, and that the size of the file is still small enough. If so, |
223 still correct, and that the size of the file is still small enough. If so, |
237 @@ -588,8 +646,10 @@ |
224 @@ -520,16 +546,12 @@ |
|
225 } |
238 } |
226 } |
239 } |
227 } |
240 |
228 - |
241 + DEBUG(D_transport) debug_printf("releasing lock\n"); |
229 - |
242 + (void)apply_lock(lockfd, F_UNLCK, 1, 120, 0, 0); |
230 -/* If *endptr is not zero, there was a syntax error in the file. */ |
|
231 - |
|
232 -else |
|
233 +else /* If *endptr is not zero, there was a syntax error in the file. */ |
|
234 { |
|
235 + time_t old_latest, new_latest; |
|
236 int len; |
|
237 - time_t old_latest, new_latest; |
|
238 uschar *tempname; |
|
239 - struct timeval tv; |
|
240 + struct timeval tv; |
|
241 |
|
242 DEBUG(D_transport) |
|
243 { |
|
244 @@ -549,6 +571,13 @@ |
|
245 |
|
246 RECALCULATE: |
|
247 |
|
248 + //hs12_lock(lockfd, F_WRLCK, "recalc"); |
|
249 + if (sigalrm_seen) |
|
250 + { |
|
251 + *excuse = "timeout while locking for recalc"; |
|
252 + return -1; |
|
253 + } |
|
254 + |
|
255 if (fd >= 0) (void)close(fd); |
|
256 old_latest = 0; |
|
257 filecount = 0; |
|
258 @@ -586,10 +615,14 @@ |
|
259 (void)close(fd); |
|
260 fd = -2; |
|
261 } |
|
262 + hs12_lock(lockfd, F_UNLCK, "done recalc"); |
|
263 } |
|
264 |
|
265 + hs12_lock(lockfd, F_UNLCK, "done check"); |
|
266 + |
|
267 + |
243 + |
268 + |
244 /* Return the sizes and the file descriptor, if any */ |
269 /* Return the sizes and the file descriptor, if any */ |
245 - |
270 - |
246 DEBUG(D_transport) debug_printf("returning maildir size=" OFF_T_FMT |
271 DEBUG(D_transport) debug_printf("returning maildir size=" OFF_T_FMT |
247 " filecount=%d\n", size, filecount); |
272 " filecount=%d\n", size, filecount); |
248 *returned_size = size; |
273 *returned_size = size; |
249 diff -r 5037ac63d7ae src/transports/tf_maildir.h |
274 diff -r d54ee7005f7f src/transports/tf_maildir.h |
250 --- a/src/transports/tf_maildir.h Sat Feb 19 13:42:16 2011 +0100 |
275 --- a/src/transports/tf_maildir.h Mon Feb 21 22:52:42 2011 +0100 |
251 +++ b/src/transports/tf_maildir.h Sun Feb 20 23:37:25 2011 +0100 |
276 +++ b/src/transports/tf_maildir.h Wed Feb 23 00:53:29 2011 +0100 |
252 @@ -16,7 +16,7 @@ |
277 @@ -16,7 +16,7 @@ |
253 uschar *); |
278 uschar *); |
254 extern int maildir_ensure_sizefile(uschar *, |
279 extern int maildir_ensure_sizefile(uschar *, |
255 appendfile_transport_options_block *, const pcre *, |
280 appendfile_transport_options_block *, const pcre *, |
256 - const pcre *, off_t *, int *); |
281 - const pcre *, off_t *, int *); |