diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp')
-rw-r--r-- | chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp index 97338704125..b1a70a13b9d 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp @@ -34,14 +34,15 @@ #include "modules/webdatabase/SQLTransactionClient.h" #include "modules/webdatabase/SQLTransactionCoordinator.h" #include "platform/Logging.h" +#include "platform/heap/glue/MessageLoopInterruptor.h" +#include "platform/heap/glue/PendingGCRunner.h" #include "public/platform/Platform.h" -#include "wtf/AutodrainedPool.h" namespace WebCore { DatabaseThread::DatabaseThread() : m_transactionClient(adoptPtr(new SQLTransactionClient())) - , m_transactionCoordinator(adoptPtr(new SQLTransactionCoordinator())) + , m_transactionCoordinator(adoptPtrWillBeNoop(new SQLTransactionCoordinator())) , m_cleanupSync(0) , m_terminationRequested(false) { @@ -49,20 +50,42 @@ DatabaseThread::DatabaseThread() DatabaseThread::~DatabaseThread() { - if (!m_terminationRequested) - requestTermination(0); + ASSERT(m_openDatabaseSet.isEmpty()); + // Oilpan: The database thread must have finished its cleanup tasks before + // the following clear(). Otherwise, WebThread destructor blocks the caller + // thread, and causes a deadlock with ThreadState cleanup. + // DatabaseContext::stop() asks the database thread to close all of + // databases, and wait until GC heap cleanup of the database thread. So we + // can safely destruct WebThread here. m_thread.clear(); } +void DatabaseThread::trace(Visitor* visitor) +{ + visitor->trace(m_openDatabaseSet); + visitor->trace(m_transactionCoordinator); +} + void DatabaseThread::start() { if (m_thread) return; m_thread = adoptPtr(blink::Platform::current()->createThread("WebCore: Database")); + m_thread->postTask(new Task(WTF::bind(&DatabaseThread::setupDatabaseThread, this))); +} + +void DatabaseThread::setupDatabaseThread() +{ + m_pendingGCRunner = adoptPtr(new PendingGCRunner); + m_messageLoopInterruptor = adoptPtr(new MessageLoopInterruptor(m_thread.get())); + m_thread->addTaskObserver(m_pendingGCRunner.get()); + ThreadState::attach(); + ThreadState::current()->addInterruptor(m_messageLoopInterruptor.get()); } -void DatabaseThread::requestTermination(DatabaseTaskSynchronizer *cleanupSync) +void DatabaseThread::requestTermination(TaskSynchronizer *cleanupSync) { + MutexLocker lock(m_terminationRequestedMutex); ASSERT(!m_terminationRequested); m_terminationRequested = true; m_cleanupSync = cleanupSync; @@ -70,13 +93,14 @@ void DatabaseThread::requestTermination(DatabaseTaskSynchronizer *cleanupSync) m_thread->postTask(new Task(WTF::bind(&DatabaseThread::cleanupDatabaseThread, this))); } -bool DatabaseThread::terminationRequested(DatabaseTaskSynchronizer* taskSynchronizer) const +bool DatabaseThread::terminationRequested(TaskSynchronizer* taskSynchronizer) const { #ifndef NDEBUG if (taskSynchronizer) taskSynchronizer->setHasCheckedForTermination(); #endif + MutexLocker lock(m_terminationRequestedMutex); return m_terminationRequested; } @@ -91,15 +115,26 @@ void DatabaseThread::cleanupDatabaseThread() // inconsistent or locked state. if (m_openDatabaseSet.size() > 0) { // As the call to close will modify the original set, we must take a copy to iterate over. - DatabaseSet openSetCopy; + WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> > openSetCopy; openSetCopy.swap(m_openDatabaseSet); - DatabaseSet::iterator end = openSetCopy.end(); - for (DatabaseSet::iterator it = openSetCopy.begin(); it != end; ++it) - (*it).get()->close(); + WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> >::iterator end = openSetCopy.end(); + for (WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> >::iterator it = openSetCopy.begin(); it != end; ++it) + (*it)->close(); } + m_thread->postTask(new Task(WTF::bind(&DatabaseThread::cleanupDatabaseThreadCompleted, this))); +} + +void DatabaseThread::cleanupDatabaseThreadCompleted() +{ + ThreadState::current()->removeInterruptor(m_messageLoopInterruptor.get()); + ThreadState::detach(); + // We need to unregister PendingGCRunner before finising this task to avoid + // PendingGCRunner::didProcessTask accesses dead ThreadState. + m_thread->removeTaskObserver(m_pendingGCRunner.get()); + if (m_cleanupSync) // Someone wanted to know when we were done cleaning up. - m_thread->postTask(new Task(WTF::bind(&DatabaseTaskSynchronizer::taskCompleted, m_cleanupSync))); + m_cleanupSync->taskCompleted(); } void DatabaseThread::recordDatabaseOpen(DatabaseBackend* database) @@ -122,6 +157,7 @@ bool DatabaseThread::isDatabaseOpen(DatabaseBackend* database) { ASSERT(isDatabaseThread()); ASSERT(database); + MutexLocker lock(m_terminationRequestedMutex); return !m_terminationRequested && m_openDatabaseSet.contains(database); } |