Bug 111642 - IndexedDB: Transactions can be started between versionchange oncomplete and openrequest onsuccess
Summary: IndexedDB: Transactions can be started between versionchange oncomplete and o...
Status: RESOLVED DUPLICATE of bug 163963
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore Misc. (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Michael Pruett
Depends on: 111643
  Show dependency treegraph
Reported: 2013-03-06 16:37 PST by Joshua Bell
Modified: 2022-07-11 15:03 PDT (History)
4 users (show)

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description Joshua Bell 2013-03-06 16:37:41 PST
As discovered in https://code.google.com/p/chromium/issues/detail?id=153064:

In multiprocess ports there's a race condition that allows a transaction to be created between the "complete" event from a "versionchange" transaction (c/o an "ugpradeneeded" handler) and the subsequent "success" event from an open() call. During this window, the database has "old" metadata, which can lead to an inconsistency:

var req = indexedDB.open("db", 1);
req.onupgradeneeded = function() {
  var db = req.result;
  req.transaction.oncomplete = function() {
    var trans = db.transaction('store'); // <---- HERE

In multiprocess ports, the line marked HERE could execute before the "success" event for the database open arrives from the backend. If it does, the db will have old metadata and raise an exception since there is no such object store. (This has a low probability because firing the "complete" and "success" events should happen with no gap in between, but depending on the IPC mechanism and context switching it could be more likely on certain OS/hardware configurations.)

But we should fix the race somehow - either by ensuring the database gets the updated metadata earlier (via the versionchange transaction) or failing the .transaction() call in the time window between the "complete" and "success" events arriving from the backend.
Comment 1 Joshua Bell 2013-03-12 13:15:40 PDT
Actually, the above repro should be fine, since the database's object store metadata is updated.

However, if an index is created in a store, the database's metadata for the store is NOT updated. So the repro needs to be.

var req = indexedDB.open("db", 1);
req.onupgradeneeded = function() {
  var db = req.result;
  db.createObjectStore('store').createIndex('index', 'keyPath');
  req.transaction.oncomplete = function() {
    db.transaction('store').objectStore('store').index('index'); // <---- HERE
Comment 2 Joshua Bell 2013-03-12 13:17:03 PDT
... and from reviewing the spec, it seems like creating the transaction should be allowed; the previous "versionchange" transaction has concluded. So just propagating the metadata update from createIndex() to the IDBDatabase object is the easiest fix.
Comment 3 Joshua Bell 2013-04-11 09:10:32 PDT
I've copied this to blink. The issue is still valid for WebKit. I'm pinging possible new owners.
Comment 4 Joshua Bell 2013-04-17 15:33:58 PDT
I posted a patch for Blink over at: https://codereview.chromium.org/14232020/

This could be relevant for multiprocess WebKit ports in the future.
Comment 5 Brent Fulgham 2022-07-11 15:03:28 PDT

*** This bug has been marked as a duplicate of bug 163963 ***