diff options
author | Owen W. Taylor <otaylor@fishsoup.net> | 2009-04-25 14:09:52 -0400 |
---|---|---|
committer | Owen W. Taylor <otaylor@fishsoup.net> | 2009-04-25 14:09:52 -0400 |
commit | cdb5d340e63094817e4eac9c3eb6fb19cf3cd595 (patch) | |
tree | 4ae23331d6479607552b2af9420282ce9fcdeed6 | |
parent | 721b1174e58e7386d1eaa113cdb3bf20d6c06c04 (diff) |
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.
-rwxr-xr-x | git-bz | 50 |
1 files changed, 40 insertions, 10 deletions
@@ -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") |