JDK-4712342 : calling Frame.setVisible() from a shutdown hook deadlocks.
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.3.1
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_nt,windows_2000
  • CPU: x86
  • Submitted: 2002-07-09
  • Updated: 2007-02-12
  • Resolved: 2007-02-12
Related Reports
Duplicate :  
Description
Name: gm110360			Date: 07/09/2002


FULL PRODUCT VERSION :
java version "1.3.1_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_03-b03)
Java HotSpot(TM) Client VM (build 1.3.1_03-b03, mixed mode)

FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
Calling setVisible on a frame from within a Shutdown hook
will result in a deadlock and the JVM not being able to be
shutdown.

Here is an example application to demonstrate the problem.
 The flag at the top enables the only workaround that I am
aware of.
<source in source section>

Doing a thread dump when in this state results in the
following for the shutdown hook thread:
---
"shutdown_hook" prio=5 tid=0x8a84c78 nid=0xb94 runnable
[0xb59f000..0xb59fdbc]
        at sun.awt.windows.WComponentPeer.hide(Native Method)
        at java.awt.Component.hide(Unknown Source)
        at java.awt.Window.hide(Unknown Source)
        at java.awt.Component.show(Unknown Source)
        at java.awt.Component.setVisible(Unknown Source)
        at AWTDeadlock.shutdown(AWTDeadlock.java:43)
        at AWTDeadlock.access$000(AWTDeadlock.java:3)
        at AWTDeadlock$1.run(AWTDeadlock.java:22)
---

This workaround is not very clean and is difficult to
implement in large systems.  How should the shutdown of
swing be handled?

Cheers,

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.  Compile the above class
2.  java -classpath ./ AWTDeadlock
3.  hit CTRL-C from the console when the frame is visible.
4.  the app will not shutdown.
5.  hit CTRL-BREAK to get the thread dump.

EXPECTED VERSUS ACTUAL BEHAVIOR :
I get the following output:
---
C:\...>java -classpath ./ AWTDeadlock
shutdownHook start
 AA
< JVM hung here >
---

Should get:
---
C:\...>java -classpath ./ AWTDeadlock
shutdownHook start
 AA
 AB
 AC
shutdownHook end
C:\...>
---


This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Frame;

public class AWTDeadlock extends Frame {
	private static final boolean WORKAROUND = false;
	
	private Thread m_hook;
	
	private AWTDeadlock() {
		super( "AWTDeadlock Example" );
		
		setSize( 400, 100 );
		setLocation( 50, 50 );
		show();
		
		// Add a shutdown hook to trap CTRL-C events.
		m_hook = new Thread( "shutdown_hook" )
		{
			public void run()
			{
				System.out.println( "shutdownHook start");
				
				shutdown();
				
				System.out.println( "shutdownHook end");
			}
		};
		Runtime.getRuntime().addShutdownHook( m_hook );
	}
	
	private void shutdown() {
		if ( WORKAROUND ) {
			// This code will workaround the problem
			if ( Thread.currentThread() != m_hook ) {
				System.out.println(" BA");
				setVisible(false);
				System.out.println(" BA");
				dispose();
				System.out.println(" BA");
			}
		} else {
			// This code will show the deadlock.
			System.out.println(" AA");
			setVisible(false);
			System.out.println(" AB");
			dispose();
			System.out.println(" AC");
		}
	}

	public static void main(String[] args) {
		new AWTDeadlock();
	}
}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
See source code.
(Review ID: 147282) 
======================================================================

Comments
EVALUATION A quick search gives a duplicate result. Close this as not a defect because the spec already has the warning about this issue.
12-02-2007

EVALUATION Runtime.addShutdownHook() spec says "Attempts to use other thread-based services such as the AWT event-dispatch thread, for example, may lead to deadlocks."
12-02-2007

EVALUATION XAWT and Motif works fine in JDK5.0 and later releases. This affects Windows only on every JDK build up to the latest JDK7.0. There are two "SIGINT handler" instances that need to work in parallel mode. The first of them waits(BLOCKED) while the second thread releases the Lock class instance which was aquired by the second thread earlier. In turn, the second thread also waits(WAITING) while all other threads finishes. Below is the stack of stopped application. Full thread dump Java HotSpot(TM) Client VM (1.6.0-rc-b103 mixed mode): "SIGINT handler" daemon prio=10 tid=0x0ab8b800 nid=0x1018 waiting for monitor entry [0x0b5cf000..0x0b5cfd94] java.lang.Thread.State: BLOCKED (on object monitor) at java.lang.Shutdown.exit(Shutdown.java:178) - waiting to lock <0x06b89c10> (a java.lang.Class for java.lang.Shutdown) at java.lang.Terminator$1.handle(Terminator.java:35) at sun.misc.Signal$1.run(Signal.java:195) at java.lang.Thread.run(Thread.java:619) "shutdown_hook" prio=6 tid=0x0ab81800 nid=0x10b8 runnable [0x0b53f000..0x0b53fa94] java.lang.Thread.State: RUNNABLE at sun.awt.windows.WComponentPeer.hide(Native Method) - locked <0x02ae2858> (a sun.awt.windows.WFramePeer) at java.awt.Component.hide(Component.java:1450) - locked <0x02a83ab8> (a java.awt.Component$AWTTreeLock) at java.awt.Window.hide(Window.java:916) at java.awt.Component.show(Component.java:1416) at java.awt.Component.setVisible(Component.java:1367) at java.awt.Window.setVisible(Window.java:818) at AWTDeadlock.shutdown(AWTDeadlock.java:43) at AWTDeadlock.access$000(AWTDeadlock.java:3) at AWTDeadlock$1.run(AWTDeadlock.java:22) "SIGINT handler" daemon prio=10 tid=0x0b07b800 nid=0xd10 in Object.wait() [0x0b49f000..0x0b49fb94] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x02af7680> (a AWTDeadlock$1) at java.lang.Thread.join(Thread.java:1143) - locked <0x02af7680> (a AWTDeadlock$1) at java.lang.Thread.join(Thread.java:1196) at java.lang.ApplicationShutdownHooks.run(ApplicationShutdownHooks.java:79) at java.lang.Shutdown.runHooks(Shutdown.java:89) at java.lang.Shutdown.sequence(Shutdown.java:133) at java.lang.Shutdown.exit(Shutdown.java:178) - locked <0x06b89c10> (a java.lang.Class for java.lang.Shutdown) at java.lang.Terminator$1.handle(Terminator.java:35) at sun.misc.Signal$1.run(Signal.java:195) at java.lang.Thread.run(Thread.java:619) "DestroyJavaVM" prio=6 tid=0x00266400 nid=0xffc waiting on condition [0x00000000..0x0095fd4c] java.lang.Thread.State: RUNNABLE "AWT-EventQueue-0" prio=6 tid=0x0b073000 nid=0xf8c in Object.wait() [0x0b44f000..0x0b44fc14] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x02adffb8> (a java.awt.EventQueue) at java.lang.Object.wait(Object.java:485) at java.awt.EventQueue.getNextEvent(EventQueue.java:477) - locked <0x02adffb8> (a java.awt.EventQueue) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:245) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160) at java.awt.EventDispatchThread.run(EventDispatchThread.java:121) "AWT-Shutdown" prio=6 tid=0x0abeac00 nid=0x1004 in Object.wait() [0x0b36f000..0x0b36fd14] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x02ae0238> (a java.lang.Object) at java.lang.Object.wait(Object.java:485) at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:263) - locked <0x02ae0238> (a java.lang.Object) at java.lang.Thread.run(Thread.java:619) "Java2D Disposer" daemon prio=10 tid=0x0b070800 nid=0x1154 in Object.wait() [0x0b31f000..0x0b31fd94] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x02ac6298> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116) - locked <0x02ac6298> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132) at sun.java2d.Disposer.run(Disposer.java:125) at java.lang.Thread.run(Thread.java:619) "Low Memory Detector" daemon prio=6 tid=0x0ab51800 nid=0xeb0 runnable [0x00000000..0x00000000] java.lang.Thread.State: RUNNABLE "CompilerThread0" daemon prio=10 tid=0x0ab50000 nid=0x970 waiting on condition [0x00000000..0x0adcf81c] java.lang.Thread.State: RUNNABLE "Attach Listener" daemon prio=10 tid=0x0ab4ec00 nid=0x914 runnable [0x00000000..0x00000000] java.lang.Thread.State: RUNNABLE "Signal Dispatcher" daemon prio=10 tid=0x0ab4e000 nid=0xff8 waiting on condition [0x00000000..0x0ad2f98c] java.lang.Thread.State: RUNNABLE "Finalizer" daemon prio=8 tid=0x0ab3d000 nid=0x1130 in Object.wait() [0x0acdf000..0x0acdfc94] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x02a50b48> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116) - locked <0x02a50b48> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159) "Reference Handler" daemon prio=10 tid=0x0ab38c00 nid=0xf88 in Object.wait() [0x0ac8f000..0x0ac8fd14] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x02a50a48> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:485) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116) - locked <0x02a50a48> (a java.lang.ref.Reference$Lock) "VM Thread" prio=10 tid=0x0ab35c00 nid=0x103c runnable "VM Periodic Task Thread" prio=10 tid=0x0ab64000 nid=0x984 waiting on condition JNI global references: 828 Heap def new generation total 960K, used 808K [0x02a50000, 0x02b50000, 0x02f30000) eden space 896K, 90% used [0x02a50000, 0x02b1a1f0, 0x02b30000) from space 64K, 0% used [0x02b30000, 0x02b30000, 0x02b40000) to space 64K, 0% used [0x02b40000, 0x02b40000, 0x02b50000) tenured generation total 4096K, used 0K [0x02f30000, 0x03330000, 0x06a50000) the space 4096K, 0% used [0x02f30000, 0x02f30000, 0x02f30200, 0x03330000) compacting perm gen total 12288K, used 5006K [0x06a50000, 0x07650000, 0x0aa50000) the space 12288K, 40% used [0x06a50000, 0x06f33ae0, 0x06f33c00, 0x07650000) No shared spaces configured.
12-02-2007