From a0f305c94f8661807c019f078dafc2ba6da70ae1 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Fri, 10 Jul 2015 07:38:53 -0700 Subject: [PATCH] Bug 1180978: Don't proceed with opening an invalidated database. r=janv,baku --- dom/indexedDB/ActorsParent.cpp | 22 +++++++++++-- dom/indexedDB/test/unit/test_blocked_order.js | 31 ++++++++++++++++++- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp index 21e9129b290..2e0cdec7453 100644 --- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -12432,6 +12432,8 @@ Database::RegisterTransaction(TransactionBase* aTransaction) MOZ_ASSERT(aTransaction); MOZ_ASSERT(!mTransactions.GetEntry(aTransaction)); MOZ_ASSERT(mDirectoryLock); + MOZ_ASSERT(!mInvalidated); + MOZ_ASSERT(!mClosed); if (NS_WARN_IF(!mTransactions.PutEntry(aTransaction, fallible))) { return false; @@ -18841,6 +18843,10 @@ FactoryOp::Run() SendResults(); return NS_OK; + // We raced, no need to crash. + case State_Completed: + return NS_OK; + default: MOZ_CRASH("Bad state!"); } @@ -18898,6 +18904,16 @@ FactoryOp::ActorDestroy(ActorDestroyReason aWhy) AssertIsOnBackgroundThread(); NoteActorDestroyed(); + + if (mState != State_SendingResults) { + // Let's see if this is right ... + MOZ_RELEASE_ASSERT(mState == State_WaitingForTransactionsToComplete); + // We didn't get an opportunity to clean up. Do that now. + mState = State_SendingResults; + IDB_REPORT_INTERNAL_ERR(); + mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + SendResults(); + } } bool @@ -19494,9 +19510,10 @@ OpenDatabaseOp::NoteDatabaseClosed(Database* aDatabase) AssertIsOnOwningThread(); MOZ_ASSERT(aDatabase); MOZ_ASSERT(mState == State_WaitingForOtherDatabasesToClose || + mState == State_WaitingForTransactionsToComplete || mState == State_DatabaseWorkVersionChange); - if (mState == State_DatabaseWorkVersionChange) { + if (mState != State_WaitingForOtherDatabasesToClose) { MOZ_ASSERT(mMaybeBlockedDatabases.IsEmpty()); MOZ_ASSERT(mRequestedVersion > aDatabase->Metadata()->mCommonMetadata.version(), @@ -19560,7 +19577,8 @@ OpenDatabaseOp::DispatchToWorkThread() MOZ_ASSERT(mMaybeBlockedDatabases.IsEmpty()); if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonMainThread()) || - IsActorDestroyed()) { + IsActorDestroyed() || + mDatabase->IsInvalidated()) { IDB_REPORT_INTERNAL_ERR(); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } diff --git a/dom/indexedDB/test/unit/test_blocked_order.js b/dom/indexedDB/test/unit/test_blocked_order.js index 3e54ccece6c..28aa3cb87cd 100644 --- a/dom/indexedDB/test/unit/test_blocked_order.js +++ b/dom/indexedDB/test/unit/test_blocked_order.js @@ -56,7 +56,7 @@ function testSteps() ok(false, "Should not receive a blocked event"); }; - event = yield undefined; + let event = yield undefined; is(event.type, "success", "Got success event"); is(databases.length, 0, "All databases with version 1 were closed"); @@ -145,6 +145,35 @@ function testSteps() is(event.type, "success", "Got success event"); + // Test 3: A blocked database left in that state should not hang shutdown. + info("Opening 1 database with version 1"); + + request = indexedDB.open(databaseName, 1); + request.onerror = errorHandler; + request.onblocked = errorHandler; + request.onsuccess = grabEventAndContinueHandler; + + event = yield undefined; + + is(event.type, "success", "Got success event"); + + db = request.result; + is(db.version, 1, "Got version 1"); + + info("Opening database with version 2"); + + request = indexedDB.open(databaseName, 2); + request.onerror = function(e) { + e.preventDefault(); + }; + request.onsuccess = errorHandler; + + request.onblocked = grabEventAndContinueHandler; + + event = yield undefined; + ok(true, "Got blocked"); + // Just allow this to remain blocked ... + finishTest(); yield undefined; }