[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

dumi at chromium.org dumi at chromium.org
Wed Dec 22 11:36:52 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 4f86babab15c7610dbf6b55fe278a95d2955e9c8
Author: dumi at chromium.org <dumi at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Jul 30 23:19:38 2010 +0000

    JavaScriptCore: Added a yield() function.
    https://bugs.webkit.org/show_bug.cgi?id=42843
    
    Reviewed by Davin Levin.
    
    * JavaScriptCore.exp:
    * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
    * wtf/Threading.h:
    * wtf/ThreadingPthreads.cpp:
    (WTF::yield):
    * wtf/ThreadingWin.cpp:
    (WTF::yield):
    * wtf/gtk/ThreadingGtk.cpp:
    (WTF::yield):
    * wtf/qt/ThreadingQt.cpp:
    (WTF::yield):
    
    WebCore: Interrupt all DB operations when the worker is terminating.
    https://bugs.webkit.org/show_bug.cgi?id=42843
    
    Reviewed by David Levin.
    
    Tests: fast/workers/storage/interrupt-database-sync.html
           fast/workers/storage/interrupt-database.html
    
    * bindings/js/JSCustomVoidCallback.cpp:
    (WebCore::JSCustomVoidCallback::~JSCustomVoidCallback): If the
    destructor is called on the context thread, delete m_data directly
    instead of posting a task to do that. We need to do that to make
    sure that all JS objects are destroyed before
    WorkerThreadShutdownFinishTask (in WorkerThread.cpp) calls
    WorkerContext::clearScript().
    
    * bindings/scripts/CodeGeneratorJS.pm: Same change as above, for
    all auto-generated callbacks.
    
    * bindings/scripts/test/JS/JSTestCallback.cpp:
    (WebCore::JSTestCallback::~JSTestCallback): Updated the
    expectations for run-bindings-tests.
    
    * platform/sql/SQLiteDatabase.cpp: Added the ability to interrupt
    all DB operations in progress, unless the database was closed or
    is being closed. Unlike sqlite3_interrupt(),
    SQLiteDatabase::interrupt() is sticky: once it's called, trying to
    run any statement on that database will fail with a
    SQLITE_INTERRUPT error code.
    (WebCore::SQLiteDatabase::SQLiteDatabase):
    (WebCore::SQLiteDatabase::close):
    (WebCore::SQLiteDatabase::interrupt):
    (WebCore::SQLiteDatabase::isInterrupted):
    
    * platform/sql/SQLiteDatabase.h: Added a mutex that can used by
    SQLiteStatement to check if the database was interrupted.
    (WebCore::SQLiteDatabase::databaseMutex):
    
    * platform/sql/SQLiteStatement.cpp: Changed prepare() and step()
    to check if the database was interrupted, before trying to prepare
    or run the statement. The other methods don't need to hold on to
    the DB lock while running, because they're fast, so we don't need
    to interrupt them.
    (WebCore::SQLiteStatement::prepare):
    (WebCore::SQLiteStatement::step):
    
    * storage/AbstractDatabase.cpp: Made SQLiteDatabase::interrupt()
    and isInterrupted() visible to WebSQLDatabases classes.
    (WebCore::AbstractDatabase::interrupt):
    (WebCore::AbstractDatabase::isInterrupted):
    * storage/AbstractDatabase.h:
    
    * storage/DatabaseTracker.cpp: Added a method to interrupt all
    databases in a given context.
    (WebCore::DatabaseTracker::interruptAllDatabasesForContext):
    * storage/DatabaseTracker.h:
    
    * storage/SQLStatement.cpp: Changed the exception/error reported
    when a statement is interrupted.
    (WebCore::SQLStatement::execute):
    * storage/SQLStatementSync.cpp:
    (WebCore::SQLStatementSync::execute):
    
    * storage/SQLTransaction.cpp: Changed the code to release the
    callback objects as soon as they're not needed.
    (WebCore::SQLTransaction::checkAndHandleClosedOrInterruptedDatabase):
    Changed this method to not schedule the next transaction step when
    the database is interrupted.
    (WebCore::SQLTransaction::performNextStep):
    (WebCore::SQLTransaction::performPendingCallback):
    (WebCore::SQLTransaction::deliverTransactionCallback):
    (WebCore::SQLTransaction::postflightAndCommit):
    (WebCore::SQLTransaction::deliverTransactionErrorCallback):
    (WebCore::SQLTransaction::cleanupAfterTransactionErrorCallback):
    * storage/SQLTransaction.h:
    
    * storage/chromium/DatabaseTrackerChromium.cpp: Added a method to
    interrupt all databases in a given context.
    (WebCore::DatabaseTracker::interruptAllDatabasesForContext):
    
    * workers/WorkerThread.cpp:
    (WebCore::WorkerThread::stop): Added a call to
    DatabaseTracker::interruptAllDatabasesForContext().
    
    LayoutTests: Test that terminating a worker interrupts all DB operations in that worker.
    https://bugs.webkit.org/show_bug.cgi?id=42843
    
    Reviewed by Davin Levin.
    
    * fast/workers/storage/interrupt-database-expected.txt: Added.
    * fast/workers/storage/interrupt-database-sync-expected.txt: Added.
    * fast/workers/storage/interrupt-database-sync.html: Added.
    * fast/workers/storage/interrupt-database.html: Added.
    * fast/workers/storage/resources/interrupt-database-sync.js: Added.
    * fast/workers/storage/resources/interrupt-database.js: Added.
    (runTransaction):
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@64384 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index b72bb65..8ac1144 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,22 @@
+2010-07-30  Dumitru Daniliuc  <dumi at chromium.org>
+
+        Reviewed by Davin Levin.
+
+        Added a yield() function.
+        https://bugs.webkit.org/show_bug.cgi?id=42843
+
+        * JavaScriptCore.exp:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+        * wtf/Threading.h:
+        * wtf/ThreadingPthreads.cpp:
+        (WTF::yield):
+        * wtf/ThreadingWin.cpp:
+        (WTF::yield):
+        * wtf/gtk/ThreadingGtk.cpp:
+        (WTF::yield):
+        * wtf/qt/ThreadingQt.cpp:
+        (WTF::yield):
+
 2010-07-30  Rafael Antognolli  <antognolli at profusion.mobi>
 
         Reviewed by Antonio Gomes.
diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp
index 93e01e2..b66d8df 100644
--- a/JavaScriptCore/JavaScriptCore.exp
+++ b/JavaScriptCore/JavaScriptCore.exp
@@ -367,6 +367,7 @@ __ZN3WTF5Mutex6unlockEv
 __ZN3WTF5Mutex7tryLockEv
 __ZN3WTF5MutexC1Ev
 __ZN3WTF5MutexD1Ev
+__ZN3WTF5yieldEv
 __ZN3WTF6strtodEPKcPPc
 __ZN3WTF7CString11mutableDataEv
 __ZN3WTF7CString16newUninitializedEmRPc
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
index a6ff1c2..a478725 100644
--- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
+++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
@@ -330,6 +330,7 @@ EXPORTS
     ?wait at ThreadCondition@WTF@@QAEXAAVMutex at 2@@Z
     ?waitForThreadCompletion at WTF@@YAHIPAPAX at Z
     ?writable at PropertyDescriptor@JSC@@QBE_NXZ
+    ?yield at WTF@@YAXXZ
     WTFLog
     WTFLogVerbose
     WTFReportArgumentAssertionFailure
diff --git a/JavaScriptCore/wtf/Threading.h b/JavaScriptCore/wtf/Threading.h
index 415a8fc..044365f 100644
--- a/JavaScriptCore/wtf/Threading.h
+++ b/JavaScriptCore/wtf/Threading.h
@@ -101,6 +101,7 @@ ThreadIdentifier currentThread();
 int waitForThreadCompletion(ThreadIdentifier, void**);
 void detachThread(ThreadIdentifier);
 
+void yield();
 
 void lockAtomicallyInitializedStaticMutex();
 void unlockAtomicallyInitializedStaticMutex();
@@ -112,5 +113,6 @@ using WTF::createThread;
 using WTF::currentThread;
 using WTF::detachThread;
 using WTF::waitForThreadCompletion;
+using WTF::yield;
 
 #endif // Threading_h
diff --git a/JavaScriptCore/wtf/ThreadingPthreads.cpp b/JavaScriptCore/wtf/ThreadingPthreads.cpp
index d01cc4a..98286d3 100644
--- a/JavaScriptCore/wtf/ThreadingPthreads.cpp
+++ b/JavaScriptCore/wtf/ThreadingPthreads.cpp
@@ -44,6 +44,7 @@
 
 #if !COMPILER(MSVC)
 #include <limits.h>
+#include <sched.h>
 #include <sys/time.h>
 #endif
 
@@ -221,6 +222,11 @@ void detachThread(ThreadIdentifier threadID)
     pthread_detach(pthreadHandle);
 }
 
+void yield()
+{
+    sched_yield();
+}
+
 ThreadIdentifier currentThread()
 {
     ThreadIdentifier id = ThreadIdentifierData::identifier();
diff --git a/JavaScriptCore/wtf/ThreadingWin.cpp b/JavaScriptCore/wtf/ThreadingWin.cpp
index c16be5a..a29fbbb 100644
--- a/JavaScriptCore/wtf/ThreadingWin.cpp
+++ b/JavaScriptCore/wtf/ThreadingWin.cpp
@@ -266,6 +266,11 @@ void detachThread(ThreadIdentifier threadID)
     clearThreadHandleForIdentifier(threadID);
 }
 
+void yield()
+{
+    ::Sleep(1);
+}
+
 ThreadIdentifier currentThread()
 {
     return static_cast<ThreadIdentifier>(GetCurrentThreadId());
diff --git a/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp b/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp
index 981eacb..863ee81 100644
--- a/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp
+++ b/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp
@@ -167,6 +167,11 @@ ThreadIdentifier currentThread()
     return establishIdentifierForThread(currentThread);
 }
 
+void yield()
+{
+    g_thread_yield();
+}
+
 Mutex::Mutex()
     : m_mutex(g_mutex_new())
 {
diff --git a/JavaScriptCore/wtf/qt/ThreadingQt.cpp b/JavaScriptCore/wtf/qt/ThreadingQt.cpp
index 7f81646..8041dea 100644
--- a/JavaScriptCore/wtf/qt/ThreadingQt.cpp
+++ b/JavaScriptCore/wtf/qt/ThreadingQt.cpp
@@ -208,6 +208,11 @@ ThreadIdentifier currentThread()
     return establishIdentifierForThread(currentThread);
 }
 
+void yield()
+{
+    QThread::yieldCurrentThread();
+}
+
 Mutex::Mutex()
     : m_mutex(new QMutex())
 {
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index e6ccc2b..02bc476 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,18 @@
+2010-07-30  Dumitru Daniliuc  <dumi at chromium.org>
+
+        Reviewed by Davin Levin.
+
+        Test that terminating a worker interrupts all DB operations in that worker.
+        https://bugs.webkit.org/show_bug.cgi?id=42843
+
+        * fast/workers/storage/interrupt-database-expected.txt: Added.
+        * fast/workers/storage/interrupt-database-sync-expected.txt: Added.
+        * fast/workers/storage/interrupt-database-sync.html: Added.
+        * fast/workers/storage/interrupt-database.html: Added.
+        * fast/workers/storage/resources/interrupt-database-sync.js: Added.
+        * fast/workers/storage/resources/interrupt-database.js: Added.
+        (runTransaction):
+
 2010-07-30  W. James MacLean  <wjmaclean at google.com>
 
         Reviewed by Nikolas Zimmermann.
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 2fef436..61706e6 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,89 @@
+2010-07-30  Dumitru Daniliuc  <dumi at chromium.org>
+
+        Reviewed by David Levin.
+
+        Interrupt all DB operations when the worker is terminating.
+        https://bugs.webkit.org/show_bug.cgi?id=42843
+
+        Tests: fast/workers/storage/interrupt-database-sync.html
+               fast/workers/storage/interrupt-database.html
+
+        * bindings/js/JSCustomVoidCallback.cpp:
+        (WebCore::JSCustomVoidCallback::~JSCustomVoidCallback): If the
+        destructor is called on the context thread, delete m_data directly
+        instead of posting a task to do that. We need to do that to make
+        sure that all JS objects are destroyed before
+        WorkerThreadShutdownFinishTask (in WorkerThread.cpp) calls
+        WorkerContext::clearScript().
+
+        * bindings/scripts/CodeGeneratorJS.pm: Same change as above, for
+        all auto-generated callbacks.
+
+        * bindings/scripts/test/JS/JSTestCallback.cpp:
+        (WebCore::JSTestCallback::~JSTestCallback): Updated the
+        expectations for run-bindings-tests.
+
+        * platform/sql/SQLiteDatabase.cpp: Added the ability to interrupt
+        all DB operations in progress, unless the database was closed or
+        is being closed. Unlike sqlite3_interrupt(),
+        SQLiteDatabase::interrupt() is sticky: once it's called, trying to
+        run any statement on that database will fail with a
+        SQLITE_INTERRUPT error code.
+        (WebCore::SQLiteDatabase::SQLiteDatabase):
+        (WebCore::SQLiteDatabase::close):
+        (WebCore::SQLiteDatabase::interrupt):
+        (WebCore::SQLiteDatabase::isInterrupted):
+
+        * platform/sql/SQLiteDatabase.h: Added a mutex that can used by
+        SQLiteStatement to check if the database was interrupted.
+        (WebCore::SQLiteDatabase::databaseMutex):
+
+        * platform/sql/SQLiteStatement.cpp: Changed prepare() and step()
+        to check if the database was interrupted, before trying to prepare
+        or run the statement. The other methods don't need to hold on to
+        the DB lock while running, because they're fast, so we don't need
+        to interrupt them.
+        (WebCore::SQLiteStatement::prepare):
+        (WebCore::SQLiteStatement::step):
+
+        * storage/AbstractDatabase.cpp: Made SQLiteDatabase::interrupt()
+        and isInterrupted() visible to WebSQLDatabases classes.
+        (WebCore::AbstractDatabase::interrupt):
+        (WebCore::AbstractDatabase::isInterrupted):
+        * storage/AbstractDatabase.h:
+
+        * storage/DatabaseTracker.cpp: Added a method to interrupt all
+        databases in a given context.
+        (WebCore::DatabaseTracker::interruptAllDatabasesForContext):
+        * storage/DatabaseTracker.h:
+
+        * storage/SQLStatement.cpp: Changed the exception/error reported
+        when a statement is interrupted.
+        (WebCore::SQLStatement::execute):
+        * storage/SQLStatementSync.cpp:
+        (WebCore::SQLStatementSync::execute):
+
+        * storage/SQLTransaction.cpp: Changed the code to release the
+        callback objects as soon as they're not needed.
+        (WebCore::SQLTransaction::checkAndHandleClosedOrInterruptedDatabase):
+        Changed this method to not schedule the next transaction step when
+        the database is interrupted.
+        (WebCore::SQLTransaction::performNextStep):
+        (WebCore::SQLTransaction::performPendingCallback):
+        (WebCore::SQLTransaction::deliverTransactionCallback):
+        (WebCore::SQLTransaction::postflightAndCommit):
+        (WebCore::SQLTransaction::deliverTransactionErrorCallback):
+        (WebCore::SQLTransaction::cleanupAfterTransactionErrorCallback):
+        * storage/SQLTransaction.h:
+
+        * storage/chromium/DatabaseTrackerChromium.cpp: Added a method to
+        interrupt all databases in a given context.
+        (WebCore::DatabaseTracker::interruptAllDatabasesForContext):
+
+        * workers/WorkerThread.cpp:
+        (WebCore::WorkerThread::stop): Added a call to
+        DatabaseTracker::interruptAllDatabasesForContext().
+
 2010-07-30  Simon Fraser  <simon.fraser at apple.com>
 
         Reviewed by Darin Adler.
diff --git a/WebCore/bindings/js/JSCustomVoidCallback.cpp b/WebCore/bindings/js/JSCustomVoidCallback.cpp
index d5c4ac3..96b5412 100644
--- a/WebCore/bindings/js/JSCustomVoidCallback.cpp
+++ b/WebCore/bindings/js/JSCustomVoidCallback.cpp
@@ -48,7 +48,10 @@ JSCustomVoidCallback::JSCustomVoidCallback(JSObject* callback, JSDOMGlobalObject
 
 JSCustomVoidCallback::~JSCustomVoidCallback()
 {
-    m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));
+    if (m_scriptExecutionContext->isContextThread())
+        delete m_data;
+    else
+        m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));
 #ifndef NDEBUG
     m_data = 0;
 #endif
diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm
index 59d2e68..247430f 100644
--- a/WebCore/bindings/scripts/CodeGeneratorJS.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm
@@ -2168,7 +2168,10 @@ sub GenerateCallbackImplementation
     # Destructor
     push(@implContent, "${className}::~${className}()\n");
     push(@implContent, "{\n");
-    push(@implContent, "    m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));\n");
+    push(@implContent, "    if (m_scriptExecutionContext->isContextThread())\n");
+    push(@implContent, "        delete m_data;\n");
+    push(@implContent, "    else\n");
+    push(@implContent, "        m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));\n");
     push(@implContent, "#ifndef NDEBUG\n");
     push(@implContent, "    m_data = 0;\n");
     push(@implContent, "#endif\n");
diff --git a/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp b/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp
index 043a6ed..6f6b568 100644
--- a/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp
+++ b/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp
@@ -43,7 +43,10 @@ JSTestCallback::JSTestCallback(JSObject* callback, JSDOMGlobalObject* globalObje
 
 JSTestCallback::~JSTestCallback()
 {
-    m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));
+    if (m_scriptExecutionContext->isContextThread())
+        delete m_data;
+    else
+        m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));
 #ifndef NDEBUG
     m_data = 0;
 #endif
diff --git a/WebCore/platform/sql/SQLiteDatabase.cpp b/WebCore/platform/sql/SQLiteDatabase.cpp
index 75fc032..05a2a22 100644
--- a/WebCore/platform/sql/SQLiteDatabase.cpp
+++ b/WebCore/platform/sql/SQLiteDatabase.cpp
@@ -31,8 +31,8 @@
 #include "Logging.h"
 #include "SQLiteFileSystem.h"
 #include "SQLiteStatement.h"
-
 #include <sqlite3.h>
+#include <wtf/Threading.h>
 
 namespace WebCore {
 
@@ -42,7 +42,7 @@ const int SQLResultOk = SQLITE_OK;
 const int SQLResultRow = SQLITE_ROW;
 const int SQLResultSchema = SQLITE_SCHEMA;
 const int SQLResultFull = SQLITE_FULL;
-
+const int SQLResultInterrupt = SQLITE_INTERRUPT;
 
 SQLiteDatabase::SQLiteDatabase()
     : m_db(0)
@@ -50,6 +50,7 @@ SQLiteDatabase::SQLiteDatabase()
     , m_transactionInProgress(false)
     , m_sharable(false)
     , m_openingThread(0)
+    , m_interrupted(false)
 {
 }
 
@@ -85,13 +86,37 @@ void SQLiteDatabase::close()
     if (m_db) {
         // FIXME: This is being called on themain thread during JS GC. <rdar://problem/5739818>
         // ASSERT(currentThread() == m_openingThread);
-        sqlite3_close(m_db);
-        m_db = 0;
+        sqlite3* db = m_db;
+        {
+            MutexLocker locker(m_databaseClosingMutex);
+            m_db = 0;
+        }
+        sqlite3_close(db);
     }
 
     m_openingThread = 0;
 }
 
+void SQLiteDatabase::interrupt()
+{
+    m_interrupted = true;
+    while (!m_lockingMutex.tryLock()) {
+        MutexLocker locker(m_databaseClosingMutex);
+        if (!m_db)
+            return;
+        sqlite3_interrupt(m_db);
+        yield();
+    }
+
+    m_lockingMutex.unlock();
+}
+
+bool SQLiteDatabase::isInterrupted()
+{
+    ASSERT(!m_lockingMutex.tryLock());
+    return m_interrupted;
+}
+
 void SQLiteDatabase::setFullsync(bool fsync) 
 {
     if (fsync) 
@@ -397,16 +422,6 @@ void SQLiteDatabase::enableAuthorizer(bool enable)
         sqlite3_set_authorizer(m_db, NULL, 0);
 }
 
-void SQLiteDatabase::lock()
-{
-    m_lockingMutex.lock();
-}
-
-void SQLiteDatabase::unlock()
-{
-    m_lockingMutex.unlock();
-}
-
 bool SQLiteDatabase::isAutoCommitOn() const
 {
     return sqlite3_get_autocommit(m_db);
diff --git a/WebCore/platform/sql/SQLiteDatabase.h b/WebCore/platform/sql/SQLiteDatabase.h
index c5924c0..8151380 100644
--- a/WebCore/platform/sql/SQLiteDatabase.h
+++ b/WebCore/platform/sql/SQLiteDatabase.h
@@ -48,6 +48,7 @@ extern const int SQLResultOk;
 extern const int SQLResultRow;
 extern const int SQLResultSchema;
 extern const int SQLResultFull;
+extern const int SQLResultInterrupt;
 
 class SQLiteDatabase : public Noncopyable {
     friend class SQLiteTransaction;
@@ -58,6 +59,8 @@ public:
     bool open(const String& filename, bool forWebSQLDatabase = false);
     bool isOpen() const { return m_db; }
     void close();
+    void interrupt();
+    bool isInterrupted();
 
     bool executeCommand(const String&);
     bool returnsAtLeastOneResult(const String&);
@@ -105,9 +108,7 @@ public:
     
     void setAuthorizer(PassRefPtr<DatabaseAuthorizer>);
 
-    // (un)locks the database like a mutex
-    void lock();
-    void unlock();
+    Mutex& databaseMutex() { return m_lockingMutex; }
     bool isAutoCommitOn() const;
 
     // The SQLite AUTO_VACUUM pragma can be either NONE, FULL, or INCREMENTAL.
@@ -149,7 +150,9 @@ private:
 
     Mutex m_lockingMutex;
     ThreadIdentifier m_openingThread;
-    
+
+    Mutex m_databaseClosingMutex;
+    bool m_interrupted;
 }; // class SQLiteDatabase
 
 } // namespace WebCore
diff --git a/WebCore/platform/sql/SQLiteStatement.cpp b/WebCore/platform/sql/SQLiteStatement.cpp
index 78bbfeb..ac467a6 100644
--- a/WebCore/platform/sql/SQLiteStatement.cpp
+++ b/WebCore/platform/sql/SQLiteStatement.cpp
@@ -61,6 +61,11 @@ SQLiteStatement::~SQLiteStatement()
 int SQLiteStatement::prepare()
 {
     ASSERT(!m_isPrepared);
+
+    MutexLocker databaseLock(m_database.databaseMutex());
+    if (m_database.isInterrupted())
+        return SQLITE_INTERRUPT;
+
     const void* tail = 0;
     LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data());
     String strippedQuery = m_query.stripWhiteSpace();
@@ -88,6 +93,11 @@ int SQLiteStatement::prepare()
 int SQLiteStatement::step()
 {
     ASSERT(m_isPrepared);
+
+    MutexLocker databaseLock(m_database.databaseMutex());
+    if (m_database.isInterrupted())
+        return SQLITE_INTERRUPT;
+
     if (!m_statement)
         return SQLITE_OK;
     LOG(SQLDatabase, "SQL - step - %s", m_query.ascii().data());
diff --git a/WebCore/storage/AbstractDatabase.cpp b/WebCore/storage/AbstractDatabase.cpp
index bcc5d06..7827ec8 100644
--- a/WebCore/storage/AbstractDatabase.cpp
+++ b/WebCore/storage/AbstractDatabase.cpp
@@ -474,6 +474,17 @@ void AbstractDatabase::incrementalVacuumIfNeeded()
         m_sqliteDatabase.runIncrementalVacuumCommand();
 }
 
+void AbstractDatabase::interrupt()
+{
+    m_sqliteDatabase.interrupt();
+}
+
+bool AbstractDatabase::isInterrupted()
+{
+    MutexLocker locker(m_sqliteDatabase.databaseMutex());
+    return m_sqliteDatabase.isInterrupted();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(DATABASE)
diff --git a/WebCore/storage/AbstractDatabase.h b/WebCore/storage/AbstractDatabase.h
index e302909..3d8d363 100644
--- a/WebCore/storage/AbstractDatabase.h
+++ b/WebCore/storage/AbstractDatabase.h
@@ -68,6 +68,8 @@ public:
 
     unsigned long long maximumSize() const;
     void incrementalVacuumIfNeeded();
+    void interrupt();
+    bool isInterrupted();
 
     // FIXME: move all version-related methods to a DatabaseVersionTracker class
     bool versionMatchesExpected() const;
diff --git a/WebCore/storage/DatabaseTracker.cpp b/WebCore/storage/DatabaseTracker.cpp
index de38ec3..0764db0 100644
--- a/WebCore/storage/DatabaseTracker.cpp
+++ b/WebCore/storage/DatabaseTracker.cpp
@@ -235,6 +235,35 @@ void DatabaseTracker::databaseChanged(AbstractDatabase* database)
     originQuotaManager().markDatabase(database);
 }
 
+void DatabaseTracker::interruptAllDatabasesForContext(const ScriptExecutionContext* context)
+{
+    Vector<RefPtr<AbstractDatabase> > openDatabases;
+    {
+        MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
+
+        if (!m_openDatabaseMap)
+            return;
+
+        DatabaseNameMap* nameMap = m_openDatabaseMap->get(context->securityOrigin());
+        if (!nameMap)
+            return;
+
+        DatabaseNameMap::const_iterator dbNameMapEndIt = nameMap->end();
+        for (DatabaseNameMap::const_iterator dbNameMapIt = nameMap->begin(); dbNameMapIt != dbNameMapEndIt; ++dbNameMapIt) {
+            DatabaseSet* databaseSet = dbNameMapIt->second;
+            DatabaseSet::const_iterator dbSetEndIt = databaseSet->end();
+            for (DatabaseSet::const_iterator dbSetIt = databaseSet->begin(); dbSetIt != dbSetEndIt; ++dbSetIt) {
+                if ((*dbSetIt)->scriptExecutionContext() == context)
+                    openDatabases.append(*dbSetIt);
+            }
+        }
+    }
+
+    Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesEndIt = openDatabases.end();
+    for (Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesIt = openDatabases.begin(); openDatabasesIt != openDatabasesEndIt; ++openDatabasesIt)
+        (*openDatabasesIt)->interrupt();
+}
+
 String DatabaseTracker::originPath(SecurityOrigin* origin) const
 {
     return SQLiteFileSystem::appendDatabaseFileNameToPath(m_databaseDirectoryPath.threadsafeCopy(), origin->databaseIdentifier());
diff --git a/WebCore/storage/DatabaseTracker.h b/WebCore/storage/DatabaseTracker.h
index 094ee66..1557f0a 100644
--- a/WebCore/storage/DatabaseTracker.h
+++ b/WebCore/storage/DatabaseTracker.h
@@ -78,6 +78,8 @@ public:
     unsigned long long getMaxSizeForDatabase(const AbstractDatabase*);
     void databaseChanged(AbstractDatabase*);
 
+    void interruptAllDatabasesForContext(const ScriptExecutionContext*);
+
 private:
     DatabaseTracker(const String& databasePath);
 
diff --git a/WebCore/storage/SQLStatement.cpp b/WebCore/storage/SQLStatement.cpp
index 2d7d78e..9dd249a 100644
--- a/WebCore/storage/SQLStatement.cpp
+++ b/WebCore/storage/SQLStatement.cpp
@@ -78,7 +78,7 @@ bool SQLStatement::execute(Database* db)
 
     if (result != SQLResultOk) {
         LOG(StorageAPI, "Unable to verify correctness of statement %s - error %i (%s)", m_statement.ascii().data(), result, database->lastErrorMsg());
-        m_error = SQLError::create(SQLError::SYNTAX_ERR, database->lastErrorMsg());
+        m_error = SQLError::create(result == SQLResultInterrupt ? SQLError::DATABASE_ERR : SQLError::SYNTAX_ERR, database->lastErrorMsg());
         return false;
     }
 
@@ -86,7 +86,7 @@ bool SQLStatement::execute(Database* db)
     // If this is the case, they might be trying to do something fishy or malicious
     if (statement.bindParameterCount() != m_arguments.size()) {
         LOG(StorageAPI, "Bind parameter count doesn't match number of question marks");
-        m_error = SQLError::create(SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match argument count");
+        m_error = SQLError::create(db->isInterrupted() ? SQLError::DATABASE_ERR : SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match argument count");
         return false;
     }
 
diff --git a/WebCore/storage/SQLStatementSync.cpp b/WebCore/storage/SQLStatementSync.cpp
index 7be3f50..e47919f 100644
--- a/WebCore/storage/SQLStatementSync.cpp
+++ b/WebCore/storage/SQLStatementSync.cpp
@@ -61,12 +61,12 @@ PassRefPtr<SQLResultSet> SQLStatementSync::execute(DatabaseSync* db, ExceptionCo
     SQLiteStatement statement(*database, m_statement);
     int result = statement.prepare();
     if (result != SQLResultOk) {
-        ec = SQLException::SYNTAX_ERR;
+        ec = (result == SQLResultInterrupt ? SQLException::DATABASE_ERR : SQLException::SYNTAX_ERR);
         return 0;
     }
 
     if (statement.bindParameterCount() != m_arguments.size()) {
-        ec = SQLException::SYNTAX_ERR;
+        ec = (db->isInterrupted()? SQLException::DATABASE_ERR : SQLException::SYNTAX_ERR);
         return 0;
     }
 
diff --git a/WebCore/storage/SQLTransaction.cpp b/WebCore/storage/SQLTransaction.cpp
index e43d844..454ea63 100644
--- a/WebCore/storage/SQLTransaction.cpp
+++ b/WebCore/storage/SQLTransaction.cpp
@@ -146,17 +146,22 @@ const char* SQLTransaction::debugStepName(SQLTransaction::TransactionStepMethod
 }
 #endif
 
-void SQLTransaction::checkAndHandleClosedDatabase()
+void SQLTransaction::checkAndHandleClosedOrInterruptedDatabase()
 {
-    if (m_database->opened())
+    if (m_database->opened() && !m_database->isInterrupted())
         return;
 
     // If the database was stopped, don't do anything and cancel queued work
-    LOG(StorageAPI, "Database was stopped - cancelling work for this transaction");
+    LOG(StorageAPI, "Database was stopped or interrupted - cancelling work for this transaction");
     MutexLocker locker(m_statementMutex);
     m_statementQueue.clear();
     m_nextStep = 0;
 
+    // Release the unneeded callbacks, to break reference cycles.
+    m_callback = 0;
+    m_successCallback = 0;
+    m_errorCallback = 0;
+
     // The next steps should be executed only if we're on the DB thread.
     if (currentThread() != database()->scriptExecutionContext()->databaseThread()->getThreadID())
         return;
@@ -183,7 +188,7 @@ bool SQLTransaction::performNextStep()
            m_nextStep == &SQLTransaction::cleanupAfterSuccessCallback ||
            m_nextStep == &SQLTransaction::cleanupAfterTransactionErrorCallback);
 
-    checkAndHandleClosedDatabase();
+    checkAndHandleClosedOrInterruptedDatabase();
 
     if (m_nextStep)
         (this->*m_nextStep)();
@@ -202,7 +207,7 @@ void SQLTransaction::performPendingCallback()
            m_nextStep == &SQLTransaction::deliverQuotaIncreaseCallback ||
            m_nextStep == &SQLTransaction::deliverSuccessCallback);
 
-    checkAndHandleClosedDatabase();
+    checkAndHandleClosedOrInterruptedDatabase();
 
     if (m_nextStep)
         (this->*m_nextStep)();
@@ -292,6 +297,7 @@ void SQLTransaction::deliverTransactionCallback()
         m_executeSqlAllowed = true;
         shouldDeliverErrorCallback = !m_callback->handleEvent(m_database->scriptExecutionContext(), this);
         m_executeSqlAllowed = false;
+        m_callback = 0;
     }
 
     // Transaction Step 5 - If the transaction callback was null or raised an exception, jump to the error callback
@@ -459,6 +465,7 @@ void SQLTransaction::postflightAndCommit()
 
     // If the commit failed, the transaction will still be marked as "in progress"
     if (m_sqliteTransaction->inProgress()) {
+        m_successCallback = 0;
         m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "failed to commit the transaction");
         handleTransactionError(false);
         return;
@@ -473,7 +480,6 @@ void SQLTransaction::postflightAndCommit()
         m_database->transactionClient()->didCommitWriteTransaction(database());
 
     // Now release our unneeded callbacks, to break reference cycles.
-    m_callback = 0;
     m_errorCallback = 0;
 
     // Transaction Step 10 - Deliver success callback, if there is one
@@ -546,8 +552,10 @@ void SQLTransaction::deliverTransactionErrorCallback()
 
     // Transaction Step 12 - If exists, invoke error callback with the last
     // error to have occurred in this transaction.
-    if (m_errorCallback)
+    if (m_errorCallback) {
         m_errorCallback->handleEvent(m_database->scriptExecutionContext(), m_transactionError.get());
+        m_errorCallback = 0;
+    }
 
     m_nextStep = &SQLTransaction::cleanupAfterTransactionErrorCallback;
     LOG(StorageAPI, "Scheduling cleanupAfterTransactionErrorCallback for transaction %p\n", this);
@@ -579,10 +587,6 @@ void SQLTransaction::cleanupAfterTransactionErrorCallback()
     ASSERT(!m_database->sqliteDatabase().transactionInProgress());
     m_nextStep = 0;
 
-    // Now release our callbacks, to break reference cycles.
-    m_callback = 0;
-    m_errorCallback = 0;
-
     // Now release the lock on this database
     m_database->transactionCoordinator()->releaseLock(this);
 }
diff --git a/WebCore/storage/SQLTransaction.h b/WebCore/storage/SQLTransaction.h
index 5c62ca2..2eb200b 100644
--- a/WebCore/storage/SQLTransaction.h
+++ b/WebCore/storage/SQLTransaction.h
@@ -87,7 +87,7 @@ private:
 
     void enqueueStatement(PassRefPtr<SQLStatement>);
 
-    void checkAndHandleClosedDatabase();
+    void checkAndHandleClosedOrInterruptedDatabase();
 
     void acquireLock();
     void openTransactionAndPreflight();
diff --git a/WebCore/storage/chromium/DatabaseTrackerChromium.cpp b/WebCore/storage/chromium/DatabaseTrackerChromium.cpp
index aad4ed9..361e203 100644
--- a/WebCore/storage/chromium/DatabaseTrackerChromium.cpp
+++ b/WebCore/storage/chromium/DatabaseTrackerChromium.cpp
@@ -174,6 +174,35 @@ unsigned long long DatabaseTracker::getMaxSizeForDatabase(const AbstractDatabase
     return databaseSize + spaceAvailable;
 }
 
+void DatabaseTracker::interruptAllDatabasesForContext(const ScriptExecutionContext* context)
+{
+    Vector<RefPtr<AbstractDatabase> > openDatabases;
+    {
+        MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
+
+        if (!m_openDatabaseMap)
+            return;
+
+        DatabaseNameMap* nameMap = m_openDatabaseMap->get(context->securityOrigin());
+        if (!nameMap)
+            return;
+
+        DatabaseNameMap::const_iterator dbNameMapEndIt = nameMap->end();
+        for (DatabaseNameMap::const_iterator dbNameMapIt = nameMap->begin(); dbNameMapIt != dbNameMapEndIt; ++dbNameMapIt) {
+            DatabaseSet* databaseSet = dbNameMapIt->second;
+            DatabaseSet::const_iterator dbSetEndIt = databaseSet->end();
+            for (DatabaseSet::const_iterator dbSetIt = databaseSet->begin(); dbSetIt != dbSetEndIt; ++dbSetIt) {
+                if ((*dbSetIt)->scriptExecutionContext() == context)
+                    openDatabases.append(*dbSetIt);
+            }
+        }
+    }
+
+    Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesEndIt = openDatabases.end();
+    for (Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesIt = openDatabases.begin(); openDatabasesIt != openDatabasesEndIt; ++openDatabasesIt)
+        (*openDatabasesIt)->interrupt();
+}
+
 }
 
 #endif // ENABLE(DATABASE)
diff --git a/WebCore/workers/WorkerThread.cpp b/WebCore/workers/WorkerThread.cpp
index 96ca89b..d6a1e05 100644
--- a/WebCore/workers/WorkerThread.cpp
+++ b/WebCore/workers/WorkerThread.cpp
@@ -30,7 +30,6 @@
 
 #include "WorkerThread.h"
 
-#include "DatabaseTask.h"
 #include "DedicatedWorkerContext.h"
 #include "KURL.h"
 #include "PlatformString.h"
@@ -41,6 +40,11 @@
 #include <utility>
 #include <wtf/Noncopyable.h>
 
+#if ENABLE(DATABASE)
+#include "DatabaseTask.h"
+#include "DatabaseTracker.h"
+#endif
+
 namespace WebCore {
 
 static Mutex& threadCountMutex()
@@ -225,6 +229,10 @@ void WorkerThread::stop()
     if (m_workerContext) {
         m_workerContext->script()->forbidExecution(WorkerScriptController::TerminateRunningScript);
 
+#if ENABLE(DATABASE)
+        DatabaseTracker::tracker().interruptAllDatabasesForContext(m_workerContext.get());
+#endif
+
     // FIXME: Rudely killing the thread won't work when we allow nested workers, because they will try to post notifications of their destruction.
     // This can likely use the same mechanism as used for databases above.
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list