Date: Fri, 26 Mar 2004 09:53:31 -0600 (CST) From: Archie Cobbs <archie@dellroad.org> To: gnome@FreeBSD.org Subject: Mozilla 1.6 patch for movemail Message-ID: <200403261553.i2QFrVEL040299@arch20m.dellroad.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200403261553.i2QFrVEL040299>