JDK-7081670 : Disposing an AppContext can lead to a spinning EventDispatchThread
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 7
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2011-08-21
  • Updated: 2014-10-15
  • Resolved: 2011-10-04
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8
7u4Fixed 8 b08Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) Server VM (build 21.0-b17, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux localhost.localdomain 2.6.40.3-0.fc15.i686 #1 SMP Tue Aug 16 04:24:09 UTC 2011 i686 i686 i386 GNU/Linux


A DESCRIPTION OF THE PROBLEM :
Disposing an AppContext can lead to a spinning EventDispatchThread.
When calling AppContext.dispose() it first calls Thread.interrupt(), and after some time Thread.stop() for Threads that didn't terminate on interrupt (quick enough).
If the EventDispatchThread belonging to an AppContext didn't terminate timely, and Thread.stop() is called for this Thread an endless loop can occur.

In EventQueue.getNextEvent condition.await() is called to wait for new events, which throws a ThreadDeath in the case Thread.stop() was called. However, because unlocking the monitor in the finally-statement also throws an Exception now, ThreadDeath is swollowed:

EventQueue.getNextEvent():
pushPopLock.lock();
            try {
                pushPopCond.await(); //Throws ThreadDeath
            } finally {
                   pushPopLock.unlock(); //Now throws IllegalMonitorException, swollows ThreadDeath.
                }

however, because the EventDispatchThread.pumpOneEventForFilters() requires catching ThreadDeath-Throwables to determine it shouls really stop (variable threadDeathCaught set to true), it never terminates. This was most likely caused by the switch from java-monitors to java.util.concurrent, as monitors don't throw an Exception if unlocking fails.

If there are still pending events in the EventQueue the thread starts spinning, because EventDispatchThread.pumpEventsForFilter(int id, Conditional cond, EventFilter filter) doesn't dispatch events if isInterrupted() returns true, and dispatching the EventQueue in run() fails (eq.detachDispatchThread(this)), because there are still events left which are not processed.

I intend to rovide patches for this through OpenJDK, just need a bug-ID.

REGRESSION.  Last worked in version 7

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
hard to reproduce, we see it pccasionally on our caciocavallo-web server

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
EventDispatchThread should terminate as expected
ACTUAL -
EventDispatchThread runs in an endless loop, not dispatching events because the thread has been interrupted, and not terminating because there are still events in the queue.

REPRODUCIBILITY :
This bug can be reproduced occasionally.

Comments
noreg-hard: it is difficult to model the state in which this bug is reproducible (see http://mail.openjdk.java.net/pipermail/awt-dev/2011-August/001858.html ). Also, according to the original bug report this issue is intermittent. However, as mentioned above in the [SQE] comment, existing tests for the EventQueue and EDT could be used to verify that this fix doesn't cause any regressions.
23-08-2013

EVALUATION The issue was initially introduced in 7b78 with a fix for 4913324.
17-11-2011

EVALUATION See http://mail.openjdk.java.net/pipermail/awt-dev/2011-September/001917.html
26-09-2011