Changeset 120954 in webkit


Ignore:
Timestamp:
Jun 21, 2012 11:54:21 AM (12 years ago)
Author:
beidson@apple.com
Message:

<rdar://problem/11718988> and https://bugs.webkit.org/show_bug.cgi?id=89673
showModalDialog fix creates risk of never returning from RunLoop::performWork, potentially blocking other event sources

In case handling a function on the queue places additional functions on the queue, we should
limit the number of functions each invocation of performWork() performs so it can return and
other event sources have a chance to spin.

The showModalDialog fix in question is http://trac.webkit.org/changeset/120879

Reviewed by Darin Adler and Anders Carlson.

  • platform/RunLoop.cpp:

(WebCore::RunLoop::performWork): If there are only N functions in the queue when performWork is called,

only handle up to N functions before returning. Any additional functions will be handled the next time
the runloop spins.

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r120953 r120954  
     12012-06-21  Brady Eidson  <beidson@apple.com>
     2
     3        <rdar://problem/11718988> and https://bugs.webkit.org/show_bug.cgi?id=89673
     4        showModalDialog fix creates risk of never returning from RunLoop::performWork, potentially blocking other event sources
     5
     6        In case handling a function on the queue places additional functions on the queue, we should
     7        limit the number of functions each invocation of performWork() performs so it can return and
     8        other event sources have a chance to spin.
     9
     10        The showModalDialog fix in question is http://trac.webkit.org/changeset/120879
     11
     12        Reviewed by Darin Adler and Anders Carlson.
     13
     14        * platform/RunLoop.cpp:
     15        (WebCore::RunLoop::performWork): If there are only N functions in the queue when performWork is called,
     16          only handle up to N functions before returning. Any additional functions will be handled the next time
     17          the runloop spins.
     18
    1192012-06-21  Tim Horton  <timothy_horton@apple.com>
    220
  • trunk/Source/WebCore/platform/RunLoop.cpp

    r120879 r120954  
    5858void RunLoop::performWork()
    5959{
     60    // It is important to handle the functions in the queue one at a time because while inside one of these
     61    // functions we might re-enter RunLoop::performWork() and we need to be able to pick up where we left off.
     62    // See http://webkit.org/b/89590 for more discussion.
     63
     64    // One possible scenario when handling the function queue is as follows:
     65    // - RunLoop::performWork() is invoked with 1 function on the queue
     66    // - Handling that function results in 1 more function being enqueued
     67    // - Handling that one results in yet another being enqueued
     68    // - And so on
     69    //
     70    // In this situation one invocation of performWork() never returns so all other event sources are blocked.
     71    // By only handling up to the number of functions that were in the queue when performWork() is called
     72    // we guarantee to occasionally return from the run loop so other event sources will be allowed to spin.
     73
    6074    Function<void()> function;
    61    
    62     while (true) {
    63         // It is important to handle the functions in the queue one at a time because while inside one of these
    64         // functions we might re-enter RunLoop::performWork() and we need to be able to pick up where we left off.
    65         // See http://webkit.org/b/89590 for more discussion.
     75    size_t functionsToHandle = 0;
    6676
     77    {
     78        MutexLocker locker(m_functionQueueLock);
     79        functionsToHandle = m_functionQueue.size();
     80
     81        if (m_functionQueue.isEmpty())
     82            return;
     83
     84        function = m_functionQueue.takeFirst();
     85    }
     86
     87    function();
     88
     89    for (size_t functionsHandled = 1; functionsHandled < functionsToHandle; ++functionsHandled) {
    6790        {
    6891            MutexLocker locker(m_functionQueueLock);
     92
     93            // Even if we start off with N functions to handle and we've only handled less than N functions, the queue
     94            // still might be empty because those functions might have been handled in an inner RunLoop::performWork().
     95            // In that case we should bail here.
    6996            if (m_functionQueue.isEmpty())
    7097                break;
Note: See TracChangeset for help on using the changeset viewer.