Mozilla 1.6 patch for movemail
Archie Cobbs
archie at dellroad.org
Fri Mar 26 08:07:00 PST 2004
Hi,
Not sure if this is useful, but here is a patch I'm using to make
the Mozilla movemail service use BSD flock() style locking for the mail
spool file instead of /var/mail/user.lock.
This patch is agains the www/mozilla port. Haven't investigated
whether www/mozilla-devel has already addressed this problem.
Cheers,
-Archie
__________________________________________________________________________
Archie Cobbs * CTO, Awarix * http://www.awarix.com
--- mailnews/local/src/nsMovemailService.cpp.orig Fri Mar 26 09:32:09 2004
+++ mailnews/local/src/nsMovemailService.cpp Fri Mar 26 09:40:43 2004
@@ -42,6 +42,7 @@
#endif
#include <unistd.h> // for link(), used in spool-file locking
+#include <fcntl.h> // for open(), used in spool-file locking
#include "prenv.h"
#include "nspr.h"
@@ -149,145 +150,17 @@
}
-PRBool ObtainSpoolLock(const char *spoolnameStr,
+int ObtainSpoolLock(const char *spoolnameStr,
int seconds /* number of seconds to retry */)
{
- // How to lock:
- // step 1: create SPOOLNAME.mozlock
- // 1a: can remove it if it already exists (probably crash-droppings)
- // step 2: hard-link SPOOLNAME.mozlock to SPOOLNAME.lock for NFS atomicity
- // 2a: if SPOOLNAME.lock is >60sec old then nuke it from orbit
- // 2b: repeat step 2 until retry-count expired or hard-link succeeds
- // step 3: remove SPOOLNAME.mozlock
- // step 4: If step 2 hard-link failed, fail hard; we do not hold the lock
- // DONE.
- //
- // (step 2a not yet implemented)
-
- nsCAutoString mozlockstr(spoolnameStr);
- mozlockstr.Append(".mozlock");
- nsCAutoString lockstr(spoolnameStr);
- lockstr.Append(".lock");
-
- nsresult rv;
-
- // Create nsFileSpec and nsILocalFile for the spool.mozlock file
- nsFileSpec tmplocspec(mozlockstr.get());
- nsCOMPtr<nsILocalFile> tmplocfile;
- rv = NS_FileSpecToIFile(&tmplocspec, getter_AddRefs(tmplocfile));
- if (NS_FAILED(rv))
- return PR_FALSE;
- // THOUGHT: hmm, perhaps use MakeUnique to generate us a unique mozlock?
- // ... perhaps not, MakeUnique implementation looks racey -- use mktemp()?
-
- // step 1: create SPOOLNAME.mozlock
-#ifdef MOVEMAIL_DEBUG
- fprintf(stderr, "\n ...... maker(%s) ......\n",
- mozlockstr.get());
-#endif
- rv = tmplocfile->Create(nsIFile::NORMAL_FILE_TYPE, 0666);
- if ( (NS_FAILED(rv) &&
- rv != NS_ERROR_FILE_ALREADY_EXISTS) ||
- !tmplocfile) {
- // can't create our .mozlock file... game over already
-#ifdef MOVEMAIL_DEBUG
- fprintf(stderr, "\n cannot create blah.mozlock file! \n");
-#endif
- return PR_FALSE;
- }
-
- // step 2: hard-link .mozlock file to .lock file (this wackiness
- // is necessary for non-racey locking on NFS-mounted spool dirs)
- // n.b. XPCOM utilities don't support hard-linking yet, so we
- // skip out to <unistd.h> and the POSIX interface for link()
- int link_result = 0;
- int retry_count = 0;
-
- do {
- link_result =
- link(mozlockstr.get(),lockstr.get());
-
- retry_count++;
-
-#ifdef MOVEMAIL_DEBUG
- fprintf(stderr, "[try#%d] ", retry_count);
-#endif
-
- if ((seconds > 0) &&
- (link_result == -1)) {
- // pause 1sec, waiting for .lock to go away
- PRIntervalTime sleepTime = 1000; // 1 second
- PR_Sleep(sleepTime);
- }
- } while ((link_result == -1) && (retry_count < seconds));
-#ifdef MOVEMAIL_DEBUG
- fprintf(stderr, "<<link result: %d>>", link_result);
-#endif
-
- // step 3: remove .mozlock file, in any case
- rv = tmplocfile->Remove(PR_FALSE /* non-recursive */);
-#ifdef MOVEMAIL_DEBUG
- if (NS_FAILED(rv)) {
- // Could not delete our .mozlock file... very unusual, but
- // not fatal.
- fprintf(stderr,
- "\nBizarre, could not delete our .mozlock file. Oh well.\n");
- }
-#endif
-
-#ifdef MOVEMAIL_DEBUG
- fprintf(stderr, "::got to the end! %s\n",
- (link_result == 0) ? "GOT LOCK" : "DID NOT GET LOCK");
-#endif
-
- // step 4: now we know whether we succeeded or failed
- if (link_result == 0)
- return PR_TRUE; // got the lock.
- else
- return PR_FALSE; // didn't. :(
+ return open(spoolnameStr, O_RDWR|O_CREAT|O_EXLOCK, 0600);
}
-// Remove our mail-spool-file lock (n.b. we should only try this if
-// we're the ones who made the lock in the first place!)
-PRBool YieldSpoolLock(const char *spoolnameStr)
+void YieldSpoolLock(int fd)
{
-#ifdef MOVEMAIL_DEBUG
- fprintf(stderr, "<<Attempting lockfile removal: %s.lock>>",
- spoolnameStr);
-#endif
-
- nsCAutoString lockstr(spoolnameStr);
- lockstr.Append(".lock");
-
- nsresult rv;
-
- // Create nsFileSpec and nsILocalFile for the spool.lock file
- nsFileSpec locklocspec(lockstr.get());
- nsCOMPtr<nsILocalFile> locklocfile;
- rv = NS_FileSpecToIFile(&locklocspec, getter_AddRefs(locklocfile));
- if (NS_FAILED(rv))
- return PR_FALSE;
-
- // Check if the lock file exists
- PRBool exists;
- rv = locklocfile->Exists(&exists);
- if (NS_FAILED(rv))
- return PR_FALSE;
-
- // Delete the file if it exists
- if (exists) {
- rv = locklocfile->Remove(PR_FALSE /* non-recursive */);
- if (NS_FAILED(rv))
- return PR_FALSE;
- }
-
-#ifdef MOVEMAIL_DEBUG
- fprintf(stderr, " LOCK YIELDING WAS SUCCESSFUL.\n");
-#endif
-
- // Success.
- return PR_TRUE;
+ if (fd != -1)
+ close(fd);
}
@@ -314,6 +187,7 @@
// we now quest for the mail spool file...
nsFileSpec spoolFileSpec;
PRBool foundSpoolFile = PR_FALSE;
+ int lock_fd = -1;
// If $(MAIL) is set then we have things easy.
char * mailEnv = PR_GetEnv("MAIL");
@@ -353,7 +227,7 @@
}
// Try and obtain the lock for the spool file
- if (!ObtainSpoolLock(wholeboxname.get(), 5)) {
+ if ((lock_fd = ObtainSpoolLock(wholeboxname.get(), 5)) == -1) {
nsAutoString lockFile = NS_ConvertUTF8toUCS2(wholeboxname);
lockFile += NS_LITERAL_STRING(".lock");
const PRUnichar *params[] = {
@@ -487,14 +361,7 @@
freebuff_and_unlock:
PR_Free(buffer);
NS_IF_RELEASE(newMailParser);
- if (!YieldSpoolLock(wholeboxname.get())) {
- nsAutoString spoolLock = NS_ConvertUTF8toUCS2(wholeboxname);
- spoolLock += NS_LITERAL_STRING(".lock");
- const PRUnichar *params[] = {
- spoolLock.get()
- };
- Error(MOVEMAIL_CANT_DELETE_LOCK, params, 1);
- }
+ YieldSpoolLock(lock_fd);
}
in_server->SetServerBusy(PR_FALSE);
More information about the freebsd-gnome
mailing list