From cdb5d340e63094817e4eac9c3eb6fb19cf3cd595 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Sat, 25 Apr 2009 14:09:52 -0400 Subject: Work around Firefox-3.5 locking problems with a copy Firefox-3.5 seems to always hold cookies.sqlite locked while the browser is open. Work around this by, when we hit a lock error, making a copy and reading from that. Not 100% reliable, but should work much of the time. --- git-bz | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/git-bz b/git-bz index 81918a5..5f8bce3 100755 --- a/git-bz +++ b/git-bz @@ -207,6 +207,7 @@ from pysqlite2 import dbapi2 as sqlite import re from StringIO import StringIO from subprocess import Popen, CalledProcessError, PIPE +import shutil import sys import tempfile import time @@ -477,19 +478,48 @@ def resolve_bug_reference(bug_reference): class CookieError(Exception): pass -def get_cookies_from_sqlite(host, cookies_sqlite, browser): +def do_get_cookies_from_sqlite(host, cookies_sqlite, browser): result = {} + # We use a timeout of 0 since we expect to hit the browser holding + # the lock often and we need to fall back to making a copy without a delay + connection = sqlite.connect(cookies_sqlite, timeout=0) - connection = sqlite.connect(cookies_sqlite) - cursor = connection.cursor() - cursor.execute("select name,value,path,expiry from moz_cookies where host = :host", { 'host': host }) + try: + cursor = connection.cursor() + cursor.execute("select name,value,path,expiry from moz_cookies where host = :host", { 'host': host }) + + now = time.time() + for name,value,path,expiry in cursor.fetchall(): + # Excessive caution: toss out values that need to be quoted in a cookie header + if float(expiry) > now and not re.search(r'[()<>@,;:\\"/\[\]?={} \t]', value): + result[name] = value + + return result + finally: + connection.close() + +# Firefox 3.5 keeps the cookies database permamently locked; as a workaround +# hack, we make a copy, read from that, then delete the copy. Of course, +# we may hit an inconsistent state of the database +def get_cookies_from_sqlite_with_copy(host, cookies_sqlite, browser): + db_copy = cookies_sqlite + ".git-bz-temp" + shutil.copyfile(cookies_sqlite, db_copy) + try: + return do_get_cookies_from_sqlite(host, db_copy, browser) + except sqlite.OperationalError, e: + raise CookieError("Cookie database was locked; temporary copy didn't work") + finally: + os.remove(db_copy) - now = time.time() - for name,value,path,expiry in cursor.fetchall(): - # Excessive caution: toss out values that need to be quoted in a cookie header - if float(expiry) > now and not re.search(r'[()<>@,;:\\"/\[\]?={} \t]', value): - result[name] = value - connection.close() +def get_cookies_from_sqlite(host, cookies_sqlite, browser): + try: + result = do_get_cookies_from_sqlite(host, cookies_sqlite, browser) + except sqlite.OperationalError, e: + if "database is locked" in str(e): + # Try making a temporary copy + result = get_cookies_from_sqlite_with_copy(host, cookies_sqlite, browser) + else: + raise if not ('Bugzilla_login' in result and 'Bugzilla_logincookie' in result): raise CookieError("You don't appear to be signed into %s; please log in with %s") -- cgit v1.2.3