summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2014-11-13 17:39:13 +0100
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2014-11-18 16:51:02 +0100
commitb9c280684065d28b52d8e4992eba8a3666899dbc (patch)
tree2ac7971c273a9f95e0c8287507c392d6f1052c5e
parente54a6126cef33a2345127ddee6f633ac57f63b5e (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.cpp15
-rw-r--r--Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.h2
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;