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