From owner-freebsd-gnome@FreeBSD.ORG Fri Mar 26 08:07:00 2004 Return-Path: Delivered-To: freebsd-gnome@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 0698B16A4CE for ; Fri, 26 Mar 2004 08:07:00 -0800 (PST) Received: from mxsf16.cluster1.charter.net (mxsf16.cluster1.charter.net [209.225.28.216]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8000843D2D for ; Fri, 26 Mar 2004 08:06:59 -0800 (PST) (envelope-from archie@dellroad.org) Received: from InterJet.dellroad.org (E6V6Q8.cpe.mvllo.al.charter.com [24.196.29.251])i2QG029Y017628 for ; Fri, 26 Mar 2004 11:00:03 -0500 (EST) (envelope-from archie@dellroad.org) Received: from arch20m.dellroad.org (arch20m.dellroad.org [10.2.2.20]) by InterJet.dellroad.org (8.9.1a/8.9.1) with ESMTP id JAA16546 for ; Fri, 26 Mar 2004 09:53:31 -0600 (CST) Received: from arch20m.dellroad.org (localhost [127.0.0.1]) by arch20m.dellroad.org (8.12.9p2/8.12.6) with ESMTP id i2QFrVdK040300 for ; Fri, 26 Mar 2004 09:53:31 -0600 (CST) (envelope-from archie@arch20m.dellroad.org) Received: (from archie@localhost) by arch20m.dellroad.org (8.12.9p2/8.12.9/Submit) id i2QFrVEL040299 for gnome@FreeBSD.org; Fri, 26 Mar 2004 09:53:31 -0600 (CST) (envelope-from archie) From: Archie Cobbs Message-Id: <200403261553.i2QFrVEL040299@arch20m.dellroad.org> To: gnome@FreeBSD.org Date: Fri, 26 Mar 2004 09:53:31 -0600 (CST) X-Mailer: ELM [version 2.4ME+ PL99b (25)] MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII Subject: Mozilla 1.6 patch for movemail X-BeenThere: freebsd-gnome@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: GNOME for FreeBSD -- porting and maintaining List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 26 Mar 2004 16:07:00 -0000 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 // for link(), used in spool-file locking +#include // 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 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 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); -#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, "<>", - spoolnameStr); -#endif - - nsCAutoString lockstr(spoolnameStr); - lockstr.Append(".lock"); - - nsresult rv; - - // Create nsFileSpec and nsILocalFile for the spool.lock file - nsFileSpec locklocspec(lockstr.get()); - nsCOMPtr 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);