diff -r d2183655483b -r 3e755b50b6a4 src.lock_maildirsize --- a/src.lock_maildirsize Sun Feb 20 23:59:48 2011 +0100 +++ b/src.lock_maildirsize Wed Feb 23 00:53:41 2011 +0100 @@ -1,18 +1,18 @@ # HG changeset patch -# Parent 5037ac63d7aece4b5e96e26bace1ab4b7e791804 +# Parent d54ee7005f7f7b5970ce45caf7487a9fd929e55f -diff -r 5037ac63d7ae Local/Makefile ---- a/Local/Makefile Sat Feb 19 13:42:16 2011 +0100 -+++ b/Local/Makefile Sun Feb 20 23:37:25 2011 +0100 +diff -r d54ee7005f7f Local/Makefile +--- a/Local/Makefile Mon Feb 21 22:52:42 2011 +0100 ++++ b/Local/Makefile Wed Feb 23 00:53:29 2011 +0100 @@ -1,4 +1,5 @@ # $Cambridge: exim/src/src/EDITME,v 1.27 2010/06/12 15:21:25 jetmore Exp $ +EXTRALIBS_EXIM=-lrt ################################################## # The Exim mail transport agent # -diff -r 5037ac63d7ae src/transports/appendfile.c ---- a/src/transports/appendfile.c Sat Feb 19 13:42:16 2011 +0100 -+++ b/src/transports/appendfile.c Sun Feb 20 23:37:25 2011 +0100 +diff -r d54ee7005f7f src/transports/appendfile.c +--- a/src/transports/appendfile.c Mon Feb 21 22:52:42 2011 +0100 ++++ b/src/transports/appendfile.c Wed Feb 23 00:53:29 2011 +0100 @@ -13,6 +13,7 @@ #ifdef SUPPORT_MAILDIR @@ -21,7 +21,38 @@ #endif -@@ -278,8 +279,8 @@ +@@ -239,6 +240,30 @@ + TRUE /* quota_is_inclusive */ + }; + ++void hs12_lock(int fd, int type, const char* msg) ++{ ++ struct timespec t0, t1; ++ clock_gettime(CLOCK_REALTIME, &t0); ++ const char *ltype = ++ type == F_UNLCK ? "UNLOCK" ++ : type == F_RDLCK ? "READ LOCK" ++ : "WRITE LOCK"; ++ ++ DEBUG(D_transport) debug_printf("%s: %s\n", ltype, msg); ++ ++ ++ (void)apply_lock(fd, type, 1, 120, 0, 0); ++ if (type == F_UNLCK) return; ++ ++ clock_gettime(CLOCK_REALTIME, &t1); ++ t1.tv_sec -= t0.tv_sec; ++ t1.tv_nsec -= t0.tv_nsec; ++ if (t1.tv_nsec < 0) { t1.tv_sec--; t1.tv_nsec *= -1; } ++ DEBUG(D_transport) ++ debug_printf("%s: %s was waiting for %d.%09d seconds\n", ++ ltype, msg, t1.tv_sec, t1.tv_nsec); ++ return; ++} + + + /************************************************* +@@ -278,8 +303,8 @@ gid = gid; if (ob->expand_maildir_use_size_file) @@ -32,7 +63,7 @@ /* Loop for quota, quota_filecount, quota_warn_threshold, mailbox_size, mailbox_filecount */ -@@ -841,7 +842,7 @@ +@@ -841,7 +866,7 @@ sigalrm_seen set if there has been a timeout */ @@ -41,7 +72,7 @@ apply_lock(int fd, int fcntltype, BOOL dofcntl, int fcntltime, BOOL doflock, int flocktime) { -@@ -887,7 +888,6 @@ +@@ -887,7 +912,6 @@ @@ -49,14 +80,11 @@ #ifdef SUPPORT_MBX /************************************************* * Copy message into MBX mailbox * -@@ -2416,18 +2416,32 @@ +@@ -2416,18 +2440,19 @@ { off_t size; int filecount; + uschar *excuse; -+ -+ struct timespec t0, t1; -+ clock_gettime(CLOCK_REALTIME, &t0); maildirsize_fd = maildir_ensure_sizefile(check_path, ob, regex, dir_regex, - &size, &filecount); @@ -67,34 +95,24 @@ addr->basic_errno = errno; - addr->message = string_sprintf("while opening or reading " - "%s/maildirsize", check_path); -+ //addr->message = string_sprintf("%s", excuse); + addr->message = excuse; return FALSE; } + -+ clock_gettime(CLOCK_REALTIME, &t1); -+ t1.tv_sec -= t0.tv_sec; -+ t1.tv_nsec -= t0.tv_nsec; -+ if (t1.tv_nsec < 0) { t1.tv_sec--; t1.tv_nsec *= -1; } -+ DEBUG(D_transport) { -+ if (t1.tv_sec >= 1) debug_printf("%s/maildirsize was locked for %d.09ld seconds\n", -+ check_path, t1.tv_sec, t1.tv_nsec); -+ } -+ if (mailbox_size < 0) mailbox_size = size; if (mailbox_filecount < 0) mailbox_filecount = filecount; } -@@ -3125,6 +3139,8 @@ +@@ -3125,6 +3150,8 @@ uschar *renamename = newname; fd = -1; -+ if (lockfd >= 0) (void)apply_lock(lockfd, F_RDLCK, 1, 120, 0, 0); // hs12 ++ if (lockfd >= 0) hs12_lock(lockfd, F_RDLCK, "delivery"); + DEBUG(D_transport) debug_printf("renaming temporary file\n"); /* If there is no rename name set, we are in a non-maildir, non-mailstore -@@ -3245,6 +3261,7 @@ +@@ -3245,6 +3272,7 @@ filename = dataname = NULL; /* Prevents attempt to unlink at end */ } } /* maildir or mailstore */ @@ -102,21 +120,21 @@ } /* successful write + close */ } /* isdirectory */ } /* write success */ -@@ -3280,6 +3297,11 @@ +@@ -3280,6 +3308,11 @@ detected, in order to get the file closed and the lock file tidied away. */ RETURN: +if (lockfd >= 0) + { -+ (void)apply_lock(lockfd, F_UNLCK, 1, 120, 0, 0); // hs12 ++ hs12_lock(lockfd, F_UNLCK, "done delivery"); + (void)close(lockfd); + } #ifdef SUPPORT_MBX if (mbx_lockfd >= 0) -diff -r 5037ac63d7ae src/transports/appendfile.h ---- a/src/transports/appendfile.h Sat Feb 19 13:42:16 2011 +0100 -+++ b/src/transports/appendfile.h Sun Feb 20 23:37:25 2011 +0100 +diff -r d54ee7005f7f src/transports/appendfile.h +--- a/src/transports/appendfile.h Mon Feb 21 22:52:42 2011 +0100 ++++ b/src/transports/appendfile.h Wed Feb 23 00:53:29 2011 +0100 @@ -95,5 +95,8 @@ /* Function that is shared with tf_maildir.c */ @@ -126,9 +144,9 @@ + /* End of transports/appendfile.h */ -diff -r 5037ac63d7ae src/transports/tf_maildir.c ---- a/src/transports/tf_maildir.c Sat Feb 19 13:42:16 2011 +0100 -+++ b/src/transports/tf_maildir.c Sun Feb 20 23:37:25 2011 +0100 +diff -r d54ee7005f7f src/transports/tf_maildir.c +--- a/src/transports/tf_maildir.c Mon Feb 21 22:52:42 2011 +0100 ++++ b/src/transports/tf_maildir.c Wed Feb 23 00:53:29 2011 +0100 @@ -367,13 +367,16 @@ Returns: >=0 a file descriptor for an open maildirsize file @@ -147,7 +165,7 @@ { int count, fd; off_t cached_quota = 0; -@@ -381,25 +384,80 @@ +@@ -381,25 +384,48 @@ int filecount = 0; int linecount = 0; off_t size = 0; @@ -157,69 +175,36 @@ uschar *ptr = buffer; uschar *endptr; +-/* Try a few times to open or create the file, in case another process is doing +-the same thing. */ +filename = string_sprintf("%s/maildirsize", path); +lockname = string_sprintf("%s.lock", filename); +hitchname = string_sprintf( "%s.%s.%08x.%08x", lockname, primary_hostname, + (unsigned int)(time(NULL)), (unsigned int)getpid()); -+ + +-filename = string_sprintf("%s/maildirsize", path); +/* Try to create a lock file. Here we should copy the loop from appendfile.c, +since our approach is quite simplified */ +lockfd = Uopen(lockname, O_CREAT|O_RDWR, ob->mode ? ob->mode : 0600); +if (lockfd < 0) -+ { -+ if (errno != ENOENT) + { + *excuse = string_sprintf("open %s", lockname); + return -1; + } + -+ lockfd = Uopen(hitchname, O_WRONLY|O_CREAT|O_EXCL, ob->mode ? ob->mode : 0600); -+ if (lockfd < 0) -+ { -+ *excuse = string_sprintf("open %s", hitchname); -+ return -1; -+ } -+ if (link(hitchname, lockname) < 0) -+ { -+ int save_errno = errno; -+ (void)unlink(hitchname); -+ errno = save_errno; -+ if (errno != EEXIST) -+ { -+ *excuse = string_sprintf("link %s -> %s", hitchname, lockname); -+ return -1; -+ } -+ (void)close(lockfd); -+ lockfd = Uopen(lockname, O_WRONLY, ob->mode ? ob->mode : 0600); -+ if (lockfd < 0) -+ { -+ *excuse = string_sprintf("open %s", lockname); -+ return -1; -+ } -+ } -+ (void)unlink(hitchname); -+ } -+ -+ +/* Before doing anything here we try to open and lock the maildirsize.lock +file. This should prevent/avoid races and parallel recalculations. We +need to do this on an extra lockfile, since the maildirsize file itself +gets renamed during the recalculation. */ + -+if (lockfd >= 0) -+(void)apply_lock(lockfd, F_WRLCK, 1, 120, 0, 0); // hs12 ++hs12_lock(lockfd, F_WRLCK, "checking"); +if (sigalrm_seen) + { + *excuse = string_sprintf("timeout locking %s", lockname); + return -1; + } -+DEBUG(D_transport) debug_printf("locked (WR) %s\n", lockname); + - /* Try a few times to open or create the file, in case another process is doing - the same thing. */ --filename = string_sprintf("%s/maildirsize", path); -- DEBUG(D_transport) debug_printf("looking for maildirsize in %s\n", path); fd = Uopen(filename, O_RDWR|O_APPEND, ob->mode ? ob->mode : 0600); -if (fd < 0) @@ -231,24 +216,64 @@ goto RECALCULATE; - } +} ++(void)lseek(fd, 0, SEEK_SET); ++ /* The file has been successfully opened. Check that the cached quota value is still correct, and that the size of the file is still small enough. If so, -@@ -588,8 +646,10 @@ +@@ -520,16 +546,12 @@ + } } } +- +- +-/* If *endptr is not zero, there was a syntax error in the file. */ +- +-else ++else /* If *endptr is not zero, there was a syntax error in the file. */ + { ++ time_t old_latest, new_latest; + int len; +- time_t old_latest, new_latest; + uschar *tempname; +- struct timeval tv; ++ struct timeval tv; -+ DEBUG(D_transport) debug_printf("releasing lock\n"); -+ (void)apply_lock(lockfd, F_UNLCK, 1, 120, 0, 0); + DEBUG(D_transport) + { +@@ -549,6 +571,13 @@ + + RECALCULATE: + ++ //hs12_lock(lockfd, F_WRLCK, "recalc"); ++ if (sigalrm_seen) ++ { ++ *excuse = "timeout while locking for recalc"; ++ return -1; ++ } ++ + if (fd >= 0) (void)close(fd); + old_latest = 0; + filecount = 0; +@@ -586,10 +615,14 @@ + (void)close(fd); + fd = -2; + } ++ hs12_lock(lockfd, F_UNLCK, "done recalc"); + } + ++ hs12_lock(lockfd, F_UNLCK, "done check"); ++ ++ + /* Return the sizes and the file descriptor, if any */ - DEBUG(D_transport) debug_printf("returning maildir size=" OFF_T_FMT " filecount=%d\n", size, filecount); *returned_size = size; -diff -r 5037ac63d7ae src/transports/tf_maildir.h ---- a/src/transports/tf_maildir.h Sat Feb 19 13:42:16 2011 +0100 -+++ b/src/transports/tf_maildir.h Sun Feb 20 23:37:25 2011 +0100 +diff -r d54ee7005f7f src/transports/tf_maildir.h +--- a/src/transports/tf_maildir.h Mon Feb 21 22:52:42 2011 +0100 ++++ b/src/transports/tf_maildir.h Wed Feb 23 00:53:29 2011 +0100 @@ -16,7 +16,7 @@ uschar *); extern int maildir_ensure_sizefile(uschar *,