Changeset 64384 in webkit


Ignore:
Timestamp:
Jul 30, 2010 4:19:38 PM (14 years ago)
Author:
dumi@chromium.org
Message:

JavaScriptCore: Added a yield() function.
https://bugs.webkit.org/show_bug.cgi?id=42843

Reviewed by Davin Levin.

(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):

Location:
trunk
Files:
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r64357 r64384  
     12010-07-30  Dumitru Daniliuc  <dumi@chromium.org>
     2
     3        Reviewed by Davin Levin.
     4
     5        Added a yield() function.
     6        https://bugs.webkit.org/show_bug.cgi?id=42843
     7
     8        * JavaScriptCore.exp:
     9        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
     10        * wtf/Threading.h:
     11        * wtf/ThreadingPthreads.cpp:
     12        (WTF::yield):
     13        * wtf/ThreadingWin.cpp:
     14        (WTF::yield):
     15        * wtf/gtk/ThreadingGtk.cpp:
     16        (WTF::yield):
     17        * wtf/qt/ThreadingQt.cpp:
     18        (WTF::yield):
     19
    1202010-07-30  Rafael Antognolli  <antognolli@profusion.mobi>
    221
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r64334 r64384  
    368368__ZN3WTF5MutexC1Ev
    369369__ZN3WTF5MutexD1Ev
     370__ZN3WTF5yieldEv
    370371__ZN3WTF6strtodEPKcPPc
    371372__ZN3WTF7CString11mutableDataEv
  • trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def

    r64334 r64384  
    331331    ?waitForThreadCompletion@WTF@@YAHIPAPAX@Z
    332332    ?writable@PropertyDescriptor@JSC@@QBE_NXZ
     333    ?yield@WTF@@YAXXZ
    333334    WTFLog
    334335    WTFLogVerbose
  • trunk/JavaScriptCore/wtf/Threading.h

    r64334 r64384  
    102102void detachThread(ThreadIdentifier);
    103103
     104void yield();
    104105
    105106void lockAtomicallyInitializedStaticMutex();
     
    113114using WTF::detachThread;
    114115using WTF::waitForThreadCompletion;
     116using WTF::yield;
    115117
    116118#endif // Threading_h
  • trunk/JavaScriptCore/wtf/ThreadingPthreads.cpp

    r64334 r64384  
    4545#if !COMPILER(MSVC)
    4646#include <limits.h>
     47#include <sched.h>
    4748#include <sys/time.h>
    4849#endif
     
    222223}
    223224
     225void yield()
     226{
     227    sched_yield();
     228}
     229
    224230ThreadIdentifier currentThread()
    225231{
  • trunk/JavaScriptCore/wtf/ThreadingWin.cpp

    r64334 r64384  
    265265        CloseHandle(threadHandle);
    266266    clearThreadHandleForIdentifier(threadID);
     267}
     268
     269void yield()
     270{
     271    ::Sleep(1);
    267272}
    268273
  • trunk/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp

    r64334 r64384  
    168168}
    169169
     170void yield()
     171{
     172    g_thread_yield();
     173}
     174
    170175Mutex::Mutex()
    171176    : m_mutex(g_mutex_new())
  • trunk/JavaScriptCore/wtf/qt/ThreadingQt.cpp

    r64334 r64384  
    209209}
    210210
     211void yield()
     212{
     213    QThread::yieldCurrentThread();
     214}
     215
    211216Mutex::Mutex()
    212217    : m_mutex(new QMutex())
  • trunk/LayoutTests/ChangeLog

    r64379 r64384  
     12010-07-30  Dumitru Daniliuc  <dumi@chromium.org>
     2
     3        Reviewed by Davin Levin.
     4
     5        Test that terminating a worker interrupts all DB operations in that worker.
     6        https://bugs.webkit.org/show_bug.cgi?id=42843
     7
     8        * fast/workers/storage/interrupt-database-expected.txt: Added.
     9        * fast/workers/storage/interrupt-database-sync-expected.txt: Added.
     10        * fast/workers/storage/interrupt-database-sync.html: Added.
     11        * fast/workers/storage/interrupt-database.html: Added.
     12        * fast/workers/storage/resources/interrupt-database-sync.js: Added.
     13        * fast/workers/storage/resources/interrupt-database.js: Added.
     14        (runTransaction):
     15
    1162010-07-30  W. James MacLean  <wjmaclean@google.com>
    217
  • trunk/WebCore/ChangeLog

    r64383 r64384  
     12010-07-30  Dumitru Daniliuc  <dumi@chromium.org>
     2
     3        Reviewed by David Levin.
     4
     5        Interrupt all DB operations when the worker is terminating.
     6        https://bugs.webkit.org/show_bug.cgi?id=42843
     7
     8        Tests: fast/workers/storage/interrupt-database-sync.html
     9               fast/workers/storage/interrupt-database.html
     10
     11        * bindings/js/JSCustomVoidCallback.cpp:
     12        (WebCore::JSCustomVoidCallback::~JSCustomVoidCallback): If the
     13        destructor is called on the context thread, delete m_data directly
     14        instead of posting a task to do that. We need to do that to make
     15        sure that all JS objects are destroyed before
     16        WorkerThreadShutdownFinishTask (in WorkerThread.cpp) calls
     17        WorkerContext::clearScript().
     18
     19        * bindings/scripts/CodeGeneratorJS.pm: Same change as above, for
     20        all auto-generated callbacks.
     21
     22        * bindings/scripts/test/JS/JSTestCallback.cpp:
     23        (WebCore::JSTestCallback::~JSTestCallback): Updated the
     24        expectations for run-bindings-tests.
     25
     26        * platform/sql/SQLiteDatabase.cpp: Added the ability to interrupt
     27        all DB operations in progress, unless the database was closed or
     28        is being closed. Unlike sqlite3_interrupt(),
     29        SQLiteDatabase::interrupt() is sticky: once it's called, trying to
     30        run any statement on that database will fail with a
     31        SQLITE_INTERRUPT error code.
     32        (WebCore::SQLiteDatabase::SQLiteDatabase):
     33        (WebCore::SQLiteDatabase::close):
     34        (WebCore::SQLiteDatabase::interrupt):
     35        (WebCore::SQLiteDatabase::isInterrupted):
     36
     37        * platform/sql/SQLiteDatabase.h: Added a mutex that can used by
     38        SQLiteStatement to check if the database was interrupted.
     39        (WebCore::SQLiteDatabase::databaseMutex):
     40
     41        * platform/sql/SQLiteStatement.cpp: Changed prepare() and step()
     42        to check if the database was interrupted, before trying to prepare
     43        or run the statement. The other methods don't need to hold on to
     44        the DB lock while running, because they're fast, so we don't need
     45        to interrupt them.
     46        (WebCore::SQLiteStatement::prepare):
     47        (WebCore::SQLiteStatement::step):
     48
     49        * storage/AbstractDatabase.cpp: Made SQLiteDatabase::interrupt()
     50        and isInterrupted() visible to WebSQLDatabases classes.
     51        (WebCore::AbstractDatabase::interrupt):
     52        (WebCore::AbstractDatabase::isInterrupted):
     53        * storage/AbstractDatabase.h:
     54
     55        * storage/DatabaseTracker.cpp: Added a method to interrupt all
     56        databases in a given context.
     57        (WebCore::DatabaseTracker::interruptAllDatabasesForContext):
     58        * storage/DatabaseTracker.h:
     59
     60        * storage/SQLStatement.cpp: Changed the exception/error reported
     61        when a statement is interrupted.
     62        (WebCore::SQLStatement::execute):
     63        * storage/SQLStatementSync.cpp:
     64        (WebCore::SQLStatementSync::execute):
     65
     66        * storage/SQLTransaction.cpp: Changed the code to release the
     67        callback objects as soon as they're not needed.
     68        (WebCore::SQLTransaction::checkAndHandleClosedOrInterruptedDatabase):
     69        Changed this method to not schedule the next transaction step when
     70        the database is interrupted.
     71        (WebCore::SQLTransaction::performNextStep):
     72        (WebCore::SQLTransaction::performPendingCallback):
     73        (WebCore::SQLTransaction::deliverTransactionCallback):
     74        (WebCore::SQLTransaction::postflightAndCommit):
     75        (WebCore::SQLTransaction::deliverTransactionErrorCallback):
     76        (WebCore::SQLTransaction::cleanupAfterTransactionErrorCallback):
     77        * storage/SQLTransaction.h:
     78
     79        * storage/chromium/DatabaseTrackerChromium.cpp: Added a method to
     80        interrupt all databases in a given context.
     81        (WebCore::DatabaseTracker::interruptAllDatabasesForContext):
     82
     83        * workers/WorkerThread.cpp:
     84        (WebCore::WorkerThread::stop): Added a call to
     85        DatabaseTracker::interruptAllDatabasesForContext().
     86
    1872010-07-30  Simon Fraser  <simon.fraser@apple.com>
    288
  • trunk/WebCore/bindings/js/JSCustomVoidCallback.cpp

    r64334 r64384  
    4949JSCustomVoidCallback::~JSCustomVoidCallback()
    5050{
    51     m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));
     51    if (m_scriptExecutionContext->isContextThread())
     52        delete m_data;
     53    else
     54        m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));
    5255#ifndef NDEBUG
    5356    m_data = 0;
  • trunk/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r64366 r64384  
    21692169    push(@implContent, "${className}::~${className}()\n");
    21702170    push(@implContent, "{\n");
    2171     push(@implContent, "    m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));\n");
     2171    push(@implContent, "    if (m_scriptExecutionContext->isContextThread())\n");
     2172    push(@implContent, "        delete m_data;\n");
     2173    push(@implContent, "    else\n");
     2174    push(@implContent, "        m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));\n");
    21722175    push(@implContent, "#ifndef NDEBUG\n");
    21732176    push(@implContent, "    m_data = 0;\n");
  • trunk/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp

    r64334 r64384  
    4444JSTestCallback::~JSTestCallback()
    4545{
    46     m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));
     46    if (m_scriptExecutionContext->isContextThread())
     47        delete m_data;
     48    else
     49        m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));
    4750#ifndef NDEBUG
    4851    m_data = 0;
  • trunk/WebCore/platform/sql/SQLiteDatabase.cpp

    r64334 r64384  
    3232#include "SQLiteFileSystem.h"
    3333#include "SQLiteStatement.h"
    34 
    3534#include <sqlite3.h>
     35#include <wtf/Threading.h>
    3636
    3737namespace WebCore {
     
    4343const int SQLResultSchema = SQLITE_SCHEMA;
    4444const int SQLResultFull = SQLITE_FULL;
    45 
     45const int SQLResultInterrupt = SQLITE_INTERRUPT;
    4646
    4747SQLiteDatabase::SQLiteDatabase()
     
    5151    , m_sharable(false)
    5252    , m_openingThread(0)
     53    , m_interrupted(false)
    5354{
    5455}
     
    8687        // FIXME: This is being called on themain thread during JS GC. <rdar://problem/5739818>
    8788        // ASSERT(currentThread() == m_openingThread);
    88         sqlite3_close(m_db);
    89         m_db = 0;
     89        sqlite3* db = m_db;
     90        {
     91            MutexLocker locker(m_databaseClosingMutex);
     92            m_db = 0;
     93        }
     94        sqlite3_close(db);
    9095    }
    9196
    9297    m_openingThread = 0;
     98}
     99
     100void SQLiteDatabase::interrupt()
     101{
     102    m_interrupted = true;
     103    while (!m_lockingMutex.tryLock()) {
     104        MutexLocker locker(m_databaseClosingMutex);
     105        if (!m_db)
     106            return;
     107        sqlite3_interrupt(m_db);
     108        yield();
     109    }
     110
     111    m_lockingMutex.unlock();
     112}
     113
     114bool SQLiteDatabase::isInterrupted()
     115{
     116    ASSERT(!m_lockingMutex.tryLock());
     117    return m_interrupted;
    93118}
    94119
     
    398423}
    399424
    400 void SQLiteDatabase::lock()
    401 {
    402     m_lockingMutex.lock();
    403 }
    404 
    405 void SQLiteDatabase::unlock()
    406 {
    407     m_lockingMutex.unlock();
    408 }
    409 
    410425bool SQLiteDatabase::isAutoCommitOn() const
    411426{
  • trunk/WebCore/platform/sql/SQLiteDatabase.h

    r64334 r64384  
    4949extern const int SQLResultSchema;
    5050extern const int SQLResultFull;
     51extern const int SQLResultInterrupt;
    5152
    5253class SQLiteDatabase : public Noncopyable {
     
    5960    bool isOpen() const { return m_db; }
    6061    void close();
     62    void interrupt();
     63    bool isInterrupted();
    6164
    6265    bool executeCommand(const String&);
     
    106109    void setAuthorizer(PassRefPtr<DatabaseAuthorizer>);
    107110
    108     // (un)locks the database like a mutex
    109     void lock();
    110     void unlock();
     111    Mutex& databaseMutex() { return m_lockingMutex; }
    111112    bool isAutoCommitOn() const;
    112113
     
    150151    Mutex m_lockingMutex;
    151152    ThreadIdentifier m_openingThread;
    152    
     153
     154    Mutex m_databaseClosingMutex;
     155    bool m_interrupted;
    153156}; // class SQLiteDatabase
    154157
  • trunk/WebCore/platform/sql/SQLiteStatement.cpp

    r64334 r64384  
    6262{
    6363    ASSERT(!m_isPrepared);
     64
     65    MutexLocker databaseLock(m_database.databaseMutex());
     66    if (m_database.isInterrupted())
     67        return SQLITE_INTERRUPT;
     68
    6469    const void* tail = 0;
    6570    LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data());
     
    8994{
    9095    ASSERT(m_isPrepared);
     96
     97    MutexLocker databaseLock(m_database.databaseMutex());
     98    if (m_database.isInterrupted())
     99        return SQLITE_INTERRUPT;
     100
    91101    if (!m_statement)
    92102        return SQLITE_OK;
  • trunk/WebCore/storage/AbstractDatabase.cpp

    r64334 r64384  
    475475}
    476476
     477void AbstractDatabase::interrupt()
     478{
     479    m_sqliteDatabase.interrupt();
     480}
     481
     482bool AbstractDatabase::isInterrupted()
     483{
     484    MutexLocker locker(m_sqliteDatabase.databaseMutex());
     485    return m_sqliteDatabase.isInterrupted();
     486}
     487
    477488} // namespace WebCore
    478489
  • trunk/WebCore/storage/AbstractDatabase.h

    r64334 r64384  
    6969    unsigned long long maximumSize() const;
    7070    void incrementalVacuumIfNeeded();
     71    void interrupt();
     72    bool isInterrupted();
    7173
    7274    // FIXME: move all version-related methods to a DatabaseVersionTracker class
  • trunk/WebCore/storage/DatabaseTracker.cpp

    r64334 r64384  
    236236}
    237237
     238void DatabaseTracker::interruptAllDatabasesForContext(const ScriptExecutionContext* context)
     239{
     240    Vector<RefPtr<AbstractDatabase> > openDatabases;
     241    {
     242        MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
     243
     244        if (!m_openDatabaseMap)
     245            return;
     246
     247        DatabaseNameMap* nameMap = m_openDatabaseMap->get(context->securityOrigin());
     248        if (!nameMap)
     249            return;
     250
     251        DatabaseNameMap::const_iterator dbNameMapEndIt = nameMap->end();
     252        for (DatabaseNameMap::const_iterator dbNameMapIt = nameMap->begin(); dbNameMapIt != dbNameMapEndIt; ++dbNameMapIt) {
     253            DatabaseSet* databaseSet = dbNameMapIt->second;
     254            DatabaseSet::const_iterator dbSetEndIt = databaseSet->end();
     255            for (DatabaseSet::const_iterator dbSetIt = databaseSet->begin(); dbSetIt != dbSetEndIt; ++dbSetIt) {
     256                if ((*dbSetIt)->scriptExecutionContext() == context)
     257                    openDatabases.append(*dbSetIt);
     258            }
     259        }
     260    }
     261
     262    Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesEndIt = openDatabases.end();
     263    for (Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesIt = openDatabases.begin(); openDatabasesIt != openDatabasesEndIt; ++openDatabasesIt)
     264        (*openDatabasesIt)->interrupt();
     265}
     266
    238267String DatabaseTracker::originPath(SecurityOrigin* origin) const
    239268{
  • trunk/WebCore/storage/DatabaseTracker.h

    r64334 r64384  
    7878    unsigned long long getMaxSizeForDatabase(const AbstractDatabase*);
    7979    void databaseChanged(AbstractDatabase*);
     80
     81    void interruptAllDatabasesForContext(const ScriptExecutionContext*);
    8082
    8183private:
  • trunk/WebCore/storage/SQLStatement.cpp

    r64334 r64384  
    7979    if (result != SQLResultOk) {
    8080        LOG(StorageAPI, "Unable to verify correctness of statement %s - error %i (%s)", m_statement.ascii().data(), result, database->lastErrorMsg());
    81         m_error = SQLError::create(SQLError::SYNTAX_ERR, database->lastErrorMsg());
     81        m_error = SQLError::create(result == SQLResultInterrupt ? SQLError::DATABASE_ERR : SQLError::SYNTAX_ERR, database->lastErrorMsg());
    8282        return false;
    8383    }
     
    8787    if (statement.bindParameterCount() != m_arguments.size()) {
    8888        LOG(StorageAPI, "Bind parameter count doesn't match number of question marks");
    89         m_error = SQLError::create(SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match argument count");
     89        m_error = SQLError::create(db->isInterrupted() ? SQLError::DATABASE_ERR : SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match argument count");
    9090        return false;
    9191    }
  • trunk/WebCore/storage/SQLStatementSync.cpp

    r64334 r64384  
    6262    int result = statement.prepare();
    6363    if (result != SQLResultOk) {
    64         ec = SQLException::SYNTAX_ERR;
     64        ec = (result == SQLResultInterrupt ? SQLException::DATABASE_ERR : SQLException::SYNTAX_ERR);
    6565        return 0;
    6666    }
    6767
    6868    if (statement.bindParameterCount() != m_arguments.size()) {
    69         ec = SQLException::SYNTAX_ERR;
     69        ec = (db->isInterrupted()? SQLException::DATABASE_ERR : SQLException::SYNTAX_ERR);
    7070        return 0;
    7171    }
  • trunk/WebCore/storage/SQLTransaction.cpp

    r64334 r64384  
    147147#endif
    148148
    149 void SQLTransaction::checkAndHandleClosedDatabase()
    150 {
    151     if (m_database->opened())
     149void SQLTransaction::checkAndHandleClosedOrInterruptedDatabase()
     150{
     151    if (m_database->opened() && !m_database->isInterrupted())
    152152        return;
    153153
    154154    // If the database was stopped, don't do anything and cancel queued work
    155     LOG(StorageAPI, "Database was stopped - cancelling work for this transaction");
     155    LOG(StorageAPI, "Database was stopped or interrupted - cancelling work for this transaction");
    156156    MutexLocker locker(m_statementMutex);
    157157    m_statementQueue.clear();
    158158    m_nextStep = 0;
     159
     160    // Release the unneeded callbacks, to break reference cycles.
     161    m_callback = 0;
     162    m_successCallback = 0;
     163    m_errorCallback = 0;
    159164
    160165    // The next steps should be executed only if we're on the DB thread.
     
    184189           m_nextStep == &SQLTransaction::cleanupAfterTransactionErrorCallback);
    185190
    186     checkAndHandleClosedDatabase();
     191    checkAndHandleClosedOrInterruptedDatabase();
    187192
    188193    if (m_nextStep)
     
    203208           m_nextStep == &SQLTransaction::deliverSuccessCallback);
    204209
    205     checkAndHandleClosedDatabase();
     210    checkAndHandleClosedOrInterruptedDatabase();
    206211
    207212    if (m_nextStep)
     
    293298        shouldDeliverErrorCallback = !m_callback->handleEvent(m_database->scriptExecutionContext(), this);
    294299        m_executeSqlAllowed = false;
     300        m_callback = 0;
    295301    }
    296302
     
    460466    // If the commit failed, the transaction will still be marked as "in progress"
    461467    if (m_sqliteTransaction->inProgress()) {
     468        m_successCallback = 0;
    462469        m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "failed to commit the transaction");
    463470        handleTransactionError(false);
     
    474481
    475482    // Now release our unneeded callbacks, to break reference cycles.
    476     m_callback = 0;
    477483    m_errorCallback = 0;
    478484
     
    547553    // Transaction Step 12 - If exists, invoke error callback with the last
    548554    // error to have occurred in this transaction.
    549     if (m_errorCallback)
     555    if (m_errorCallback) {
    550556        m_errorCallback->handleEvent(m_database->scriptExecutionContext(), m_transactionError.get());
     557        m_errorCallback = 0;
     558    }
    551559
    552560    m_nextStep = &SQLTransaction::cleanupAfterTransactionErrorCallback;
     
    580588    m_nextStep = 0;
    581589
    582     // Now release our callbacks, to break reference cycles.
    583     m_callback = 0;
    584     m_errorCallback = 0;
    585 
    586590    // Now release the lock on this database
    587591    m_database->transactionCoordinator()->releaseLock(this);
  • trunk/WebCore/storage/SQLTransaction.h

    r64334 r64384  
    8888    void enqueueStatement(PassRefPtr<SQLStatement>);
    8989
    90     void checkAndHandleClosedDatabase();
     90    void checkAndHandleClosedOrInterruptedDatabase();
    9191
    9292    void acquireLock();
  • trunk/WebCore/storage/chromium/DatabaseTrackerChromium.cpp

    r64334 r64384  
    175175}
    176176
     177void DatabaseTracker::interruptAllDatabasesForContext(const ScriptExecutionContext* context)
     178{
     179    Vector<RefPtr<AbstractDatabase> > openDatabases;
     180    {
     181        MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
     182
     183        if (!m_openDatabaseMap)
     184            return;
     185
     186        DatabaseNameMap* nameMap = m_openDatabaseMap->get(context->securityOrigin());
     187        if (!nameMap)
     188            return;
     189
     190        DatabaseNameMap::const_iterator dbNameMapEndIt = nameMap->end();
     191        for (DatabaseNameMap::const_iterator dbNameMapIt = nameMap->begin(); dbNameMapIt != dbNameMapEndIt; ++dbNameMapIt) {
     192            DatabaseSet* databaseSet = dbNameMapIt->second;
     193            DatabaseSet::const_iterator dbSetEndIt = databaseSet->end();
     194            for (DatabaseSet::const_iterator dbSetIt = databaseSet->begin(); dbSetIt != dbSetEndIt; ++dbSetIt) {
     195                if ((*dbSetIt)->scriptExecutionContext() == context)
     196                    openDatabases.append(*dbSetIt);
     197            }
     198        }
     199    }
     200
     201    Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesEndIt = openDatabases.end();
     202    for (Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesIt = openDatabases.begin(); openDatabasesIt != openDatabasesEndIt; ++openDatabasesIt)
     203        (*openDatabasesIt)->interrupt();
     204}
     205
    177206}
    178207
  • trunk/WebCore/workers/WorkerThread.cpp

    r64334 r64384  
    3131#include "WorkerThread.h"
    3232
    33 #include "DatabaseTask.h"
    3433#include "DedicatedWorkerContext.h"
    3534#include "KURL.h"
     
    4241#include <wtf/Noncopyable.h>
    4342
     43#if ENABLE(DATABASE)
     44#include "DatabaseTask.h"
     45#include "DatabaseTracker.h"
     46#endif
     47
    4448namespace WebCore {
    4549
     
    226230        m_workerContext->script()->forbidExecution(WorkerScriptController::TerminateRunningScript);
    227231
     232#if ENABLE(DATABASE)
     233        DatabaseTracker::tracker().interruptAllDatabasesForContext(m_workerContext.get());
     234#endif
     235
    228236    // FIXME: Rudely killing the thread won't work when we allow nested workers, because they will try to post notifications of their destruction.
    229237    // This can likely use the same mechanism as used for databases above.
Note: See TracChangeset for help on using the changeset viewer.