diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2014-11-13 17:39:13 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2014-11-18 16:51:02 +0100 |
commit | b9c280684065d28b52d8e4992eba8a3666899dbc (patch) | |
tree | 2ac7971c273a9f95e0c8287507c392d6f1052c5e | |
parent | e54a6126cef33a2345127ddee6f633ac57f63b5e (diff) |
Fix race-condition crash on leaving pages using Indexed DB
ScriptExecutionContext does not allow the list of active DOM objects
to change while it is iterating over it. Since the IDB transaction
backend implementations holds several active DOM objects it should
not delete itself while aborting.
Change-Id: Icd2f5b5a3f1957461b9a253d1005896bb2461466
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
-rw-r--r-- | Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp | 15 | ||||
-rw-r--r-- | Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.h | 2 |
2 files changed, 16 insertions, 1 deletions
diff --git a/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp b/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp index 656255770..1e3e32b2d 100644 --- a/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp +++ b/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp @@ -57,6 +57,7 @@ IDBTransactionBackendImpl::IDBTransactionBackendImpl(int64_t id, PassRefPtr<IDBD , m_database(database) , m_transaction(database->backingStore().get()) , m_taskTimer(this, &IDBTransactionBackendImpl::taskTimerFired) + , m_asyncDerefTimer(this, &IDBTransactionBackendImpl::asyncDerefTimerFired) , m_pendingPreemptiveEvents(0) { // We pass a reference of this object before it can be adopted. @@ -106,7 +107,7 @@ void IDBTransactionBackendImpl::abort(PassRefPtr<IDBDatabaseError> error) // The last reference to this object may be released while performing the // abort steps below. We therefore take a self reference to keep ourselves // alive while executing this method. - RefPtr<IDBTransactionBackendImpl> protect(this); + this->ref(); m_state = Finished; m_taskTimer.stop(); @@ -138,6 +139,18 @@ void IDBTransactionBackendImpl::abort(PassRefPtr<IDBDatabaseError> error) m_database->transactionFinishedAndAbortFired(this); m_database = 0; + + if (this->refCount() == 1) { + // We may already be iterating over active DOM Objects which would make it illegal + // to cause ourselves to be deleted here. + m_asyncDerefTimer.startOneShot(0); + } else + this->deref(); +} + +void IDBTransactionBackendImpl::asyncDerefTimerFired(Timer<IDBTransactionBackendImpl>*) +{ + this->deref(); } bool IDBTransactionBackendImpl::isTaskQueueEmpty() const diff --git a/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.h b/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.h index 3718e61c6..1a5a962e3 100644 --- a/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.h +++ b/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.h @@ -87,6 +87,7 @@ private: bool hasPendingTasks() const; void taskTimerFired(Timer<IDBTransactionBackendImpl>*); + void asyncDerefTimerFired(Timer<IDBTransactionBackendImpl>*); void closeOpenCursors(); const int64_t m_id; @@ -107,6 +108,7 @@ private: // FIXME: delete the timer once we have threads instead. Timer<IDBTransactionBackendImpl> m_taskTimer; + Timer<IDBTransactionBackendImpl> m_asyncDerefTimer; int m_pendingPreemptiveEvents; HashSet<IDBCursorBackendImpl*> m_openCursors; |