[Webkit-unassigned] [Bug 28207] New: Another deadlock in the DB code

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Tue Aug 11 18:33:27 PDT 2009


           Summary: Another deadlock in the DB code
           Product: WebKit
           Version: 528+ (Nightly build)
          Platform: All
        OS/Version: All
            Status: UNCONFIRMED
          Severity: Normal
          Priority: P2
         Component: New Bugs
        AssignedTo: webkit-unassigned at lists.webkit.org
        ReportedBy: dumi at chromium.org
                CC: andersca at apple.com, beidson at apple.com,
                    aroben at apple.com, michaeln at google.com,
                    dglazkov at chromium.org

Bug 27966 describes how 2 transactions run on 2 different handles to the same
DB can deadlock the DB thread. Here's an example of how a transaction combined
with a openDatabase() call can deadlock the DB thread and block the main thread
at the same time:

1: var db1 = openDatabase("SomeDB", "1.0", "Blah", 10000);
2: db1.transaction(function(tx) {
3:     tx.executeSql("SomeWriteStatement", [args],
4:         function(result) { var db2 = openDatabase("SomeDB", "1.0", "Blah",
10000); },
5:         function(tx, error) { });
6:     },
7:     function(error) { },
8:     function() { }
9: );

1. The user opens a handle to a database (line #1).
2. The user starts running a transaction on that handle (line #2). The
transaction must have a "write" statement, that will make SQLite acquire an
exclusive lock on the DB file (line #3).
3. Eventually, we get to running the statement callback (line #4).
4. openDatabase() is called on the main thread (line #4).
5. The main thread creates a new SQLite connection to the same DB file,
schedules a task on the DB thread (to make sure the version is correct), and
blocks waiting for this task to complete (openDatabase() is a sync call
according to the spec).
6. In order to check the version, the new task needs to acquire a "read" lock
on the DB file first and check if the __WebKitDatabaseInfoTable__ table exists.
7. This "read" lock cannot be acquired because the transaction has an exclusive
lock on the DB file. At the same time, the transaction cannot release the
exclusive lock until the statement callback is executed. So the DB thread is
deadlocked, and the main thread is blocked too, because it waits for the
openDatabase() call to finish.

Safari's debug build from trunk deadlocks for 30 seconds (SQLite's
busy_timeout) and then crashes.


It's OK for the first call to openDatabase(SomeDB, ...) to execute SQL
statements, because we know there are no in-flight transactions on other DB
handles to the same database. However, the 2nd, 3rd, ... calls to
openDatabase(SomeDB, ...) cannot run any SQL statements without risking a
deadlock. So in addition to caching the DB version (this is what WebCore does
now), we need to also cache a flag that tells us if the
__WebKitDatabaseInfoTable__ exists in the database.

Configure bugmail: https://bugs.webkit.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

More information about the webkit-unassigned mailing list