From b567077e439237252ccd1b427b06f24f4889c620 Mon Sep 17 00:00:00 2001 From: Shawn Wilsher Date: Fri, 20 Nov 2009 12:35:45 -0800 Subject: [PATCH] Bug 525356 - windows debug unit tests: test_connection_executeAsync.js and test_statement_executeAsync.js failing frequently (fatal assertion) Release on the calling thread so when the connections destructor is called, it is not on the background thread. r=asuth a=dbaron --HG-- extra : rebase_source : c546987a611b92ca319f17faf4163a3f5bc257f5 --- storage/src/mozStorageConnection.cpp | 6 +++--- storage/src/mozStorageConnection.h | 12 ++++++------ storage/src/mozStorageStatement.cpp | 20 ++++++++++++++++++-- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/storage/src/mozStorageConnection.cpp b/storage/src/mozStorageConnection.cpp index 56aa9b625b3..42fc1f1afb5 100644 --- a/storage/src/mozStorageConnection.cpp +++ b/storage/src/mozStorageConnection.cpp @@ -289,6 +289,7 @@ private: Connection::Connection(Service *aService) : sharedAsyncExecutionMutex("Connection::sharedAsyncExecutionMutex") +, threadOpenedOn(do_GetCurrentThread()) , mDBConn(nsnull) , mAsyncExecutionMutex("Connection::mAsyncExecutionMutex") , mAsyncExecutionThreadShuttingDown(false) @@ -297,7 +298,6 @@ Connection::Connection(Service *aService) , mFunctionsMutex(nsAutoLock::NewLock("FunctionsMutex")) , mProgressHandlerMutex(nsAutoLock::NewLock("ProgressHandlerMutex")) , mProgressHandler(nsnull) -, mOpenedThread(do_GetCurrentThread()) , mStorageService(aService) { mFunctions.Init(); @@ -517,7 +517,7 @@ Connection::setClosedState() { // Ensure that we are on the correct thread to close the database. PRBool onOpenedThread; - nsresult rv = mOpenedThread->IsOnCurrentThread(&onOpenedThread); + nsresult rv = threadOpenedOn->IsOnCurrentThread(&onOpenedThread); NS_ENSURE_SUCCESS(rv, rv); if (!onOpenedThread) { NS_ERROR("Must close the database on the thread that you opened it with!"); @@ -550,7 +550,7 @@ Connection::internalClose() { // Ensure that we are being called on the thread we were opened with. PRBool onOpenedThread = PR_FALSE; - (void)mOpenedThread->IsOnCurrentThread(&onOpenedThread); + (void)threadOpenedOn->IsOnCurrentThread(&onOpenedThread); NS_ASSERTION(onOpenedThread, "Not called on the thread the database was opened on!"); } diff --git a/storage/src/mozStorageConnection.h b/storage/src/mozStorageConnection.h index 827d4e4bf5b..a396f8bb1db 100644 --- a/storage/src/mozStorageConnection.h +++ b/storage/src/mozStorageConnection.h @@ -100,6 +100,12 @@ public: */ Mutex sharedAsyncExecutionMutex; + /** + * References the thread this database was opened on. This MUST be thread it + * is closed on. + */ + const nsCOMPtr threadOpenedOn; + /** * Closes the SQLite database, and warns about any non-finalized statements. */ @@ -180,12 +186,6 @@ private: PRLock *mProgressHandlerMutex; nsCOMPtr mProgressHandler; - /** - * References the thread this database was opened on. This MUST be thread it - * is closed on. - */ - nsCOMPtr mOpenedThread; - // This is here for two reasons: 1) It's used to make sure that the // connections do not outlive the service. 2) Our custom collating functions // call its localeCompareStrings() method. diff --git a/storage/src/mozStorageStatement.cpp b/storage/src/mozStorageStatement.cpp index 1036a1f28e7..cf342e3b571 100644 --- a/storage/src/mozStorageStatement.cpp +++ b/storage/src/mozStorageStatement.cpp @@ -43,6 +43,7 @@ #include "nsError.h" #include "nsMemory.h" +#include "nsProxyRelease.h" #include "nsThreadUtils.h" #include "nsIClassInfoImpl.h" #include "nsIProgrammingLanguage.h" @@ -77,18 +78,33 @@ namespace { class AsyncStatementFinalizer : public nsRunnable { public: - AsyncStatementFinalizer(sqlite3_stmt *aStatement) + /** + * Constructor for the event. + * + * @param aStatement + * The sqlite3_stmt to finalize on the background thread. + * @param aConnection + * The Connection that aStatement was created on. We hold a reference + * to this to ensure that if we are the last reference to the + * Connection, that we release it on the proper thread. The release + * call is proxied to the appropriate thread. + */ + AsyncStatementFinalizer(sqlite3_stmt *aStatement, + Connection *aConnection) : mStatement(aStatement) + , mConnection(aConnection) { } NS_IMETHOD Run() { (void)::sqlite3_finalize(mStatement); + (void)::NS_ProxyRelease(mConnection->threadOpenedOn, mConnection); return NS_OK; } private: sqlite3_stmt *mStatement; + nsCOMPtr mConnection; }; } // anonymous namespace @@ -401,7 +417,7 @@ Statement::Finalize() } else { nsCOMPtr event = - new AsyncStatementFinalizer(mCachedAsyncStatement); + new AsyncStatementFinalizer(mCachedAsyncStatement, mDBConnection); NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY); nsresult rv = target->Dispatch(event, NS_DISPATCH_NORMAL);