United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 4701990 Headless mode hang on exit when Toolkit is accessed
4701990 : Headless mode hang on exit when Toolkit is accessed

Details
Type:
Bug
Submit Date:
2002-06-13
Status:
Resolved
Updated Date:
2003-04-12
Project Name:
JDK
Resolved Date:
2002-09-06
Component:
client-libs
OS:
solaris_8
Sub-Component:
java.awt
CPU:
sparc
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.1
Fixed Versions:
1.4.2

Related Reports
Relates:
Relates:

Sub Tasks

Description
This bug occurs on Solaris and Linux.

It the Toolkit is accessed when running in Headless mode, the Java app will hang on exit.  The following test can be used to reproduce this:

---
import java.awt.*;

public class GetToolkit {
    public static void main(String[] args) {
        Toolkit tk = Toolkit.getDefaultToolkit();
    }
}
---

When run normally, this program runs to completion and then exits.  When run w/ -Djava.awt.headless=true, the app never exits.  This is true on Solaris w/ 1.4 & 1.4.1b14, and on Linux with 1.4.1b14.  The thread dump looks like this:

Full thread dump Java HotSpot(TM) Client VM (1.4.1-beta-b14 mixed mode):

"DestroyJavaVM" prio=5 tid=0x2c518 nid=0x1 waiting on condition [0..ffbfe194]

"AWT-Shutdown" prio=5 tid=0x1860d8 nid=0x9 in Object.wait() [f23ff000..f23ffc24]
        at java.lang.Object.wait(Native Method)
        - waiting on <f2c9dea8> (a java.lang.Object)
        at java.lang.Object.wait(Object.java:426)
        at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:259)
        - locked <f2c9dea8> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:536)

"Signal Dispatcher" daemon prio=10 tid=0xb8fd0 nid=0x7 waiting on condition [0..0]

"Finalizer" daemon prio=8 tid=0xb43d8 nid=0x4 in Object.wait() [f2b7f000..f2b7fc24]
        at java.lang.Object.wait(Native Method)
        - waiting on <f2c00490> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:111)
        - locked <f2c00490> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:127)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=10 tid=0xb39a0 nid=0x3 in Object.wait() [facff000..facffc24]
        at java.lang.Object.wait(Native Method)
        - waiting on <f2c00380> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:426)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:113)
        - locked <f2c00380> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=5 tid=0xb2578 nid=0x2 runnable 

"VM Periodic Task Thread" prio=10 tid=0xb7d20 nid=0x5 waiting on condition 
"Suspend Checker Thread" prio=10 tid=0xb8678 nid=0x6 runnable 

                                    

Comments
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
mantis
mantis-b02

FIXED IN:
mantis
mantis-b02

INTEGRATED IN:
mantis
mantis-b02


                                     
2004-06-14
SUGGESTED FIX



Name: dsR10078			Date: 06/25/2002


Do not set the "toolkit thread busy" early in SunToolkit constructor. 
Instead, set it just before the toolkit thread starts.

This fix moves the point at which AWTAutoShutdown state is changed. As
such it might cause regressions of two types: 
1)the application exits unexpectedly, as AWT shuts down prematurely;
2)the application hangs, as AWT doesn't shutdown when expected.

This fix affects only the boolean "toolkit thread busy" flag. This
flag is initially set when the singleton Toolkit instance is
created. After that, platform-specific {M|W}Toolkit constructors start
the toolkit thread and all further modifications to this flag are
performed from the toolkit thread.

Let's W1 and W2 denote Mantis running in the same conditions
(application, options, user actions, timings and so on) without the
fix and with the fix respectively.

For both W1 and W2 the flag is set before the toolkit thread
starts. In W2 the flag is set later than in W1.

Before the flag is initially set in W1 and after the flag is
initially set in W2, W1 and W2 become identical, so the regression
could only happen because of the difference in behavior between W1
and W2 in the interval T when the flag is set in W1 and cleared in W2.

In W1 AWT cannot shutdown in the interval T, since this flag must be
cleared before AWT shutdown is triggered. This guarantees that if AWT
shuts down in W1 then AWT shuts down in W2. For this reason the
regression of the second type is not possible.

Let's consider the regression of the first type: W2 exits, W1 doesn't
exit. Since W1 doesn't exit, W2 can exit only because AWT shuts down
in W2 in the interval T. W2 can exit because of shutdown only if there
are no alive non-daemon threads at some point in the interval T. This
implies that the thread that creates the singleton Toolkit instance is
a daemon thread.

So, the regression of the first type could only happen if the Toolkit
instance is created on a daemon thread and there is a point in the
interval T at which there are no alive non-daemon threads. In this
scenario W1 can also exit depending on timings unless the application 
synchronizes some non-daemon thread with operations performed by the
Toolkit constructors in the interval T, so that this non-daemon thread
exits just after some of these operations is performed.

It is very unlikely that this situation can occur in some existing
application, but we should keep it in mind.

After this fix is applied, another problem manifests - the
AWT shutdown uses SunToolkit.postEvent to post shutdown events to
all event dispatch threads. SunToolkit.postEvent eventually invokes
SunToolkit.wakeupEventQueue. SunToolkit.wakeupEventQueue is a native
method that is not included in headless library. As a result AWT
shutdown fails with UnsafisfiedLinkerError. Additional fix is to
include SunToolkit.wakeupEventQueue in headless library.

###@###.### 2002-06-14

======================================================================

Name: dsR10078			Date: 06/27/2002


Use of native methods to bypass access restrictions is a bad style 
and should be avoided if possible. An alternative solution for this 
case is not to use SunToolkit.postEvent to post shutdown events, but
call EventQueue.postEvent directly instead. 

Since client code can install a custom EventQueue (either via
"AWT.EventQueueClass" property or with EventQueue.push),
EventQueue.postEvent should only be called on the thread that belongs
to the thread group of the AppContext associated with this
EventQueue. The solution is to check if the AppContext associated with
the EventQueue is different from the current AppContext and if it is,
create a new daemon thread (within the appropriate thread group) that
will invoke EventQueue.postEvent.

Additionally, we should take care of the class loader to be used to
execute EventQueue.postEvent (see similar bug 4378087). The problem is
that if we don't set an appropriate class loader for the thread that
invokes EventQueue.postEvent, it can fail to load classes. The
heuristic is to save off a reference to the context ClassLoader used
to create the AppContext and set this ClassLoader for the thread.

###@###.### 2002-06-14

======================================================================
                                     
2002-06-14
EVALUATION

Commit to fix in mantis (hang). 
###@###.### 2002-06-13


Name: dsR10078			Date: 06/14/2002



The bug is reproducible on Solaris/Linux. It doesn't manifest on
Windows.

The automatic shutdown implementation uses a boolean flag "toolkit
thread busy" that indicates whether the toolkit thread processes a
native event or waits for a new event to appear on the native event
queue.

Automatic shutdown starts only if this flag is cleared. The current
implementation initially sets this flag in SunToolkit constructor. 
When the toolkit thread starts, it clears the flag every time it
enters idle state and sets it back when it exits idle state.

On Solaris/Linux, the toolkit thread is not started in headless mode,
so the flag is never cleared and automatic shutdown never starts.
On Windows, the toolkit thread is started even if in headless mode, so
the flag is cleared and AWT shuts down properly.

###@###.### 2002-06-14

======================================================================
                                     
2002-06-14



Hardware and Software, Engineered to Work Together