<AWT Dev> [7u6] Review request for 7177040: Deadlock between PostEventQueue.noEvents, EventQueue.isDispatchThread and SwingUtilities.invokeLater

David Holmes david.holmes at oracle.com
Thu Jul 12 14:10:38 PDT 2012


On 12/07/2012 10:18 PM, Anthony Petrov wrote:
> On 07/12/12 05:41, David Holmes wrote:

<snip>

>> It also seems that with this fix the interrupted EDT will not detach due
>> to the flush being in progress. The EDT will resume the pumpEvents loop
>> in its run() method. If the interrupt state of the EDT has not been
>> maintained then the fact it was interrupted (and should detach?) is now
>> lost. If it is maintained then presumably we will try to
>> detachDispatchThread again, in which case the EDT will enter a busy
>> polling loop trying, but failing, to detach, until the flush() has
>> actually completed.
>
> When interrupt() is called on EDT, the shutdown flag is set, which is
> subsequently passed as the forceDetach parameter to
> detachDispatchingThread(). If the parameter is true, the detaching
> happens unconditionally. So this shouldn't be an issue.

I don't quite follow this part. The logic is:

  if (!forceDetach && (peekEvent() != null) ||
                       !SunToolkit.isPostEventQueueEmpty()) {
      return false;
  }

If forceDetach is true then we won't execute peekEvent() and 
isPostEventQueueEmpty(), which means we would not have hit the original 
deadlock.

Oleg's response seems to indicate that we will indeed keep looping but 
because of the values of various flags we won't do anything "useful". 
But that is the kind of "busy wait" that I was referring to.

Cheers,
David



> --
> best regards,
> Anthony
>
>
>>
>> Cheers,
>> David
>>
>>>
>>> Thanks,
>>> Oleg
>>>
>>> 7/11/2012 7:35 PM, Anthony Petrov wrote:
>>>> Hi Oleg,
>>>>
>>>> 1. I suggest to rename isPending to isFlushing, as it reflects the
>>>> current state of the PostEventQueue more precisely.
>>>>
>>>> 2. I suggest to use the try{}finally{} pattern to set/reset the new
>>>> flag in the flush() method to ensure the flag is reset even if the
>>>> while() loop throws an exception.
>>>>
>>>> Otherwise the fix looks good.
>>>>
>>>> --
>>>> best regards,
>>>> Anthony
>>>>
>>>> On 7/11/2012 7:24 PM, Oleg Pekhovskiy wrote:
>>>>> Hi!
>>>>>
>>>>> Please review the fix for CR:
>>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7177040
>>>>>
>>>>> Webrev:
>>>>> http://cr.openjdk.java.net/~bagiras/7u6/7177040.1
>>>>>
>>>>> The idea of the fix is that there are two concurrent threads that try
>>>>> to get two synchronization objects EventQueue.pushPopLock and
>>>>> PostEventQueue itself.
>>>>> For NetBeans these threads are (EDT & WarmUp) or (EDT & TimerQueue).
>>>>> Problem happens when EDT is interrupted and goes to
>>>>> EventQueue.detachDispatchThread() where EventQueue.pushPopLock is
>>>>> owned and
>>>>> EDT is waiting to own PostEventQueue when calling
>>>>> SunToolkit.isPostEventQueueEmpty() -> PostEventQueue.noEvents().
>>>>> At the same time another thread calls EventQueue.postEvent() that
>>>>> calls EventQueue.flushPendingEvents() -> PostEventQueue.flush() where
>>>>> PostEventQueue is owned
>>>>> and another thread is waiting to own EventQueue.pushPopLock when
>>>>> calling EventQueue.postEvent() -> EventQueue.postEventPrivate().
>>>>>
>>>>> To avoid potential deadlock I moved synchronization out of
>>>>> postEvent()'s cycle in PostEventQueue.flush(),
>>>>> but to be clear about the existence of Events that are not posted to
>>>>> EventQueue yet I added PostEventQueue.isPending flag that is true
>>>>> until the end of the cycle.
>>>>>
>>>>> There are only two classes that utilize PostEventQueue.flush()
>>>>> method: SunToolkit.flushPendingEvents() and
>>>>> SunToolkitSubclass.flushPendingEvents().
>>>>> They are both synchronized by static SunToolkit.flushLock. That
>>>>> eliminates the situation when we have overlapped calls of
>>>>> PostEventQueue.flush().
>>>>>
>>>>> Thanks,
>>>>> Oleg
>>>



More information about the awt-dev mailing list