Commit 0c099fc8 authored by dumi@chromium.org's avatar dumi@chromium.org

Making sure that all in-progress transactions are rolled back on

the database thread before they're destroyed. Otherwise,
SQLiteTransaction's destructor will try to do a rollback and that
would cause an assertion failure, if the object is not destroyed
on the DB thread.

Reviewed by Eric Seidel.

https://bugs.webkit.org/show_bug.cgi?id=34152

* platform/sql/SQLiteTransaction.cpp:
(WebCore::SQLiteTransaction::stop):
* storage/SQLTransaction.cpp:
(WebCore::SQLTransaction::notifyDatabaseThreadIsShuttingDown):
* storage/SQLTransaction.h:
* storage/SQLTransactionCoordinator.cpp:
(WebCore::SQLTransactionCoordinator::shutdown):



git-svn-id: svn://svn.chromium.org/blink/trunk@54162 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 226bb49b
2010-02-01 Dumitru Daniliuc <dumi@chromium.org>
Reviewed by Eric Seidel.
Making sure that all in-progress transactions are rolled back on
the database thread before they're destroyed. Otherwise,
SQLiteTransaction's destructor will try to do a rollback and that
would cause an assertion failure, if the object is not destroyed
on the DB thread.
https://bugs.webkit.org/show_bug.cgi?id=34152
* platform/sql/SQLiteTransaction.cpp:
(WebCore::SQLiteTransaction::stop):
* storage/SQLTransaction.cpp:
(WebCore::SQLTransaction::notifyDatabaseThreadIsShuttingDown):
* storage/SQLTransaction.h:
* storage/SQLTransactionCoordinator.cpp:
(WebCore::SQLTransactionCoordinator::shutdown):
2010-02-01 Sam Weinig <sam@webkit.org> 2010-02-01 Sam Weinig <sam@webkit.org>
Reviewed by Beth Dakin. Reviewed by Beth Dakin.
......
...@@ -64,6 +64,11 @@ void SQLiteTransaction::begin() ...@@ -64,6 +64,11 @@ void SQLiteTransaction::begin()
void SQLiteTransaction::commit() void SQLiteTransaction::commit()
{ {
// FIXME: this code is buggy; it assumes that COMMIT always succeeds which is not the case:
// the transaction could've been silently rolled back before getting to the COMMIT statement
// (https://bugs.webkit.org/show_bug.cgi?id=34280). However, the rest of the code does not
// know how to deal with a premature rollback and a failed COMMIT at this moment, so until
// we figure out what to do with bug 34280, it's better to leave this code as it is.
if (m_inProgress) { if (m_inProgress) {
ASSERT(m_db.m_transactionInProgress); ASSERT(m_db.m_transactionInProgress);
m_db.executeCommand("COMMIT;"); m_db.executeCommand("COMMIT;");
...@@ -84,8 +89,10 @@ void SQLiteTransaction::rollback() ...@@ -84,8 +89,10 @@ void SQLiteTransaction::rollback()
void SQLiteTransaction::stop() void SQLiteTransaction::stop()
{ {
m_inProgress = false; if (m_inProgress) {
m_db.m_transactionInProgress = false; m_inProgress = false;
m_db.m_transactionInProgress = false;
}
} }
} // namespace WebCore } // namespace WebCore
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "Database.h" #include "Database.h"
#include "DatabaseAuthorizer.h" #include "DatabaseAuthorizer.h"
#include "DatabaseDetails.h" #include "DatabaseDetails.h"
#include "DatabaseThread.h"
#include "ExceptionCode.h" #include "ExceptionCode.h"
#include "Logging.h" #include "Logging.h"
#include "Page.h" #include "Page.h"
...@@ -83,6 +84,7 @@ SQLTransaction::SQLTransaction(Database* db, PassRefPtr<SQLTransactionCallback> ...@@ -83,6 +84,7 @@ SQLTransaction::SQLTransaction(Database* db, PassRefPtr<SQLTransactionCallback>
SQLTransaction::~SQLTransaction() SQLTransaction::~SQLTransaction()
{ {
ASSERT(!m_sqliteTransaction);
} }
void SQLTransaction::executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback> callback, PassRefPtr<SQLStatementErrorCallback> callbackError, ExceptionCode& e) void SQLTransaction::executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback> callback, PassRefPtr<SQLStatementErrorCallback> callbackError, ExceptionCode& e)
...@@ -203,6 +205,16 @@ void SQLTransaction::performPendingCallback() ...@@ -203,6 +205,16 @@ void SQLTransaction::performPendingCallback()
(this->*m_nextStep)(); (this->*m_nextStep)();
} }
void SQLTransaction::notifyDatabaseThreadIsShuttingDown()
{
ASSERT(currentThread() == database()->scriptExecutionContext()->databaseThread()->getThreadID());
// If the transaction is in progress, we should roll it back here, since this is our last
// oportunity to do something related to this transaction on the DB thread.
// Clearing m_sqliteTransaction invokes SQLiteTransaction's destructor which does just that.
m_sqliteTransaction.clear();
}
void SQLTransaction::acquireLock() void SQLTransaction::acquireLock()
{ {
m_database->transactionCoordinator()->acquireLock(this); m_database->transactionCoordinator()->acquireLock(this);
...@@ -491,6 +503,7 @@ void SQLTransaction::cleanupAfterSuccessCallback() ...@@ -491,6 +503,7 @@ void SQLTransaction::cleanupAfterSuccessCallback()
// There is no next step // There is no next step
LOG(StorageAPI, "Transaction %p is complete\n", this); LOG(StorageAPI, "Transaction %p is complete\n", this);
ASSERT(!m_database->m_sqliteDatabase.transactionInProgress()); ASSERT(!m_database->m_sqliteDatabase.transactionInProgress());
m_sqliteTransaction.clear();
m_nextStep = 0; m_nextStep = 0;
// Release the lock on this database // Release the lock on this database
......
...@@ -80,6 +80,7 @@ public: ...@@ -80,6 +80,7 @@ public:
Database* database() { return m_database.get(); } Database* database() { return m_database.get(); }
bool isReadOnly() { return m_readOnly; } bool isReadOnly() { return m_readOnly; }
void notifyDatabaseThreadIsShuttingDown();
private: private:
SQLTransaction(Database*, PassRefPtr<SQLTransactionCallback>, PassRefPtr<SQLTransactionErrorCallback>, SQLTransaction(Database*, PassRefPtr<SQLTransactionCallback>, PassRefPtr<SQLTransactionErrorCallback>,
......
...@@ -109,6 +109,20 @@ void SQLTransactionCoordinator::releaseLock(SQLTransaction* transaction) ...@@ -109,6 +109,20 @@ void SQLTransactionCoordinator::releaseLock(SQLTransaction* transaction)
void SQLTransactionCoordinator::shutdown() void SQLTransactionCoordinator::shutdown()
{ {
// Notify all transactions in progress that the database thread is shutting down
for (CoordinationInfoMap::iterator coordinationInfoIterator = m_coordinationInfoMap.begin();
coordinationInfoIterator != m_coordinationInfoMap.end(); ++coordinationInfoIterator) {
CoordinationInfo& info = coordinationInfoIterator->second;
if (info.activeWriteTransaction)
info.activeWriteTransaction->notifyDatabaseThreadIsShuttingDown();
for (HashSet<RefPtr<SQLTransaction> >::iterator activeReadTransactionsIterator =
info.activeReadTransactions.begin();
activeReadTransactionsIterator != info.activeReadTransactions.end();
++activeReadTransactionsIterator) {
(*activeReadTransactionsIterator)->notifyDatabaseThreadIsShuttingDown();
}
}
// Clean up all pending transactions for all databases // Clean up all pending transactions for all databases
m_coordinationInfoMap.clear(); m_coordinationInfoMap.clear();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment