Changeset 30811 in webkit


Ignore:
Timestamp:
Mar 5, 2008, 2:26:34 PM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

Reviewed by Alexey and Mark Rowe

Fix for <rdar://problem/5778247> - Reproducible crash on storage/execute-sql-args.html

DatabaseThread::unscheduleDatabaseTasks() manually filters through a MessageQueue,
removing particular items for Databases that were shutting down.

This filtering operation is not atomic, and therefore causes a race condition with the
MessageQueue waking up and reading from the message queue.

The end result was an attempt to dereference a null DatabaseTask. Timing-wise, this never
seemed to happen in a debug build, otherwise an assertion would've caught it. Replacing that
assertion with a crash in a release build is what revealed this bug.

  • wtf/MessageQueue.h: (WTF::::waitForMessage): Tweak the waiting logic to check the queue's empty state then go back to sleep if the queue was empty - checking m_killed each time it wakes up.

WebCore:

Reviewed by Alexey and Mark Rowe

Fix for <rdar://problem/5778247> - Reproducible crash on storage/execute-sql-args.html

DatabaseThread::unscheduleDatabaseTasks() manually filters through a MessageQueue,
removing particular items for Databases that were shutting down.

This filtering operation is not atomic, and therefore causes a race condition with the
database thread waking up and reading from the message queue.

The end result was an attempt to dereference a null DatabaseTask. Timing-wise, this never
seemed to happen in a debug build, otherwise an assertion would've caught it. Replacing that
assertion with a crash in a release build is what revealed this bug.

The fix for the above symptom was entirely in WTF::MessageQueue in JSCore. With this fix in
place, another crash popped up in the layout tests that was related to dereferencing a
deallocated object - simply because SQLTransaction had a raw pointer to it's Database object
when it needed to be a ref pointer.

  • storage/SQLTransaction.cpp: (WebCore::SQLTransaction::runCurrentStatement):
  • storage/SQLTransaction.h: Change m_database to be a RefPtr (WebCore::SQLTransaction::database):

LayoutTests:

Reviewed by Alexey + Mark Rowe

Fix for <rdar://problem/5778247> - Reproducible crash on storage/execute-sql-args.html

This test takes its best shot at handling two databases on a single database thread at once,
then having one of those databases go away completely (garbage collection and everything)

  • storage/multiple-databases-garbage-collection-expected.txt: Added.
  • storage/multiple-databases-garbage-collection.html: Added.
Location:
trunk
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r30810 r30811  
     12008-03-05  Brady Eidson  <[email protected]>
     2
     3        Reviewed by Alexey and Mark Rowe
     4
     5        Fix for <rdar://problem/5778247> - Reproducible crash on storage/execute-sql-args.html
     6
     7        DatabaseThread::unscheduleDatabaseTasks() manually filters through a MessageQueue,
     8        removing particular items for Databases that were shutting down.
     9
     10        This filtering operation is not atomic, and therefore causes a race condition with the
     11        MessageQueue waking up and reading from the message queue. 
     12
     13        The end result was an attempt to dereference a null DatabaseTask.  Timing-wise, this never
     14        seemed to happen in a debug build, otherwise an assertion would've caught it.  Replacing that
     15        assertion with a crash in a release build is what revealed this bug.
     16
     17        * wtf/MessageQueue.h:
     18        (WTF::::waitForMessage): Tweak the waiting logic to check the queue's empty state then go back
     19          to sleep if the queue was empty - checking m_killed each time it wakes up.
     20
    1212008-03-05  David D. Kilzer  <[email protected]>
    222
  • trunk/JavaScriptCore/wtf/MessageQueue.h

    r30522 r30811  
    7676    {
    7777        MutexLocker lock(m_mutex);
    78         if (m_killed)
    79             return false;
    8078       
    81         if (m_queue.isEmpty())
     79        while (!m_killed && m_queue.isEmpty())
    8280            m_condition.wait(m_mutex);
     81
    8382        if (m_killed)
    8483            return false;
  • trunk/LayoutTests/ChangeLog

    r30790 r30811  
     12008-03-05  Brady Eidson  <[email protected]>
     2
     3        Reviewed by Alexey + Mark Rowe
     4
     5        Fix for <rdar://problem/5778247> - Reproducible crash on storage/execute-sql-args.html
     6
     7        This test takes its best shot at handling two databases on a single database thread at once,
     8        then having one of those databases go away completely (garbage collection and everything)
     9
     10        * storage/multiple-databases-garbage-collection-expected.txt: Added.
     11        * storage/multiple-databases-garbage-collection.html: Added.
     12
    1132008-03-04  Maciej Stachowiak  <[email protected]>
    214
  • trunk/WebCore/ChangeLog

    r30809 r30811  
     12008-03-05  Brady Eidson  <[email protected]>
     2
     3        Reviewed by Alexey and Mark Rowe
     4
     5        Fix for <rdar://problem/5778247> - Reproducible crash on storage/execute-sql-args.html
     6
     7        DatabaseThread::unscheduleDatabaseTasks() manually filters through a MessageQueue,
     8        removing particular items for Databases that were shutting down.
     9
     10        This filtering operation is not atomic, and therefore causes a race condition with the
     11        database thread waking up and reading from the message queue. 
     12
     13        The end result was an attempt to dereference a null DatabaseTask.  Timing-wise, this never
     14        seemed to happen in a debug build, otherwise an assertion would've caught it.  Replacing that
     15        assertion with a crash in a release build is what revealed this bug.
     16
     17        The fix for the above symptom was entirely in WTF::MessageQueue in JSCore.  With this fix in
     18        place, another crash popped up in the layout tests that was related to dereferencing a
     19        deallocated object - simply because SQLTransaction had a raw pointer to it's Database object
     20        when it needed to be a ref pointer.
     21
     22        * storage/SQLTransaction.cpp:
     23        (WebCore::SQLTransaction::runCurrentStatement):
     24        * storage/SQLTransaction.h: Change m_database to be a RefPtr
     25        (WebCore::SQLTransaction::database):
     26
    1272008-03-05  Mark Rowe  <[email protected]>
    228
  • trunk/WebCore/storage/SQLTransaction.cpp

    r30331 r30811  
    309309    m_database->m_databaseAuthorizer->reset();
    310310   
    311     if (m_currentStatement->execute(m_database)) {
     311    if (m_currentStatement->execute(m_database.get())) {
    312312        if (m_database->m_databaseAuthorizer->lastActionChangedDatabase()) {
    313313            // Flag this transaction as having changed the database for later delegate notification
     
    317317            Locker<OriginQuotaManager> locker(manager);
    318318           
    319             manager.markDatabase(m_database);
     319            manager.markDatabase(m_database.get());
    320320        }
    321321           
  • trunk/WebCore/storage/SQLTransaction.h

    r30522 r30811  
    7474    void performPendingCallback();
    7575   
    76     Database* database() { return m_database; }
     76    Database* database() { return m_database.get(); }
    7777
    7878private:
     
    108108    bool m_executeSqlAllowed;
    109109   
    110     Database* m_database;
     110    RefPtr<Database> m_database;
    111111    RefPtr<SQLTransactionWrapper> m_wrapper;
    112112    RefPtr<SQLTransactionCallback> m_callback;
Note: See TracChangeset for help on using the changeset viewer.