JDK-6660258 : Java application stops Windows logout/shutdown (regression in 1.5.0_14)
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 5.0
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2008-02-07
  • Updated: 2013-09-12
  • Resolved: 2009-12-03
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.
Other JDK 6 JDK 7
5.0u23 b01Fixed 6u51Fixed 7Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_14"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_14-b03)
Java HotSpot(TM) Client VM (build 1.5.0_14-b03, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
A simple "hello world" Swing application (code attached) does not exit when the users logs out or shuts down Windows XP, halting the logout process.  The user is presented with the standard windows dialog indicating that a process is not responding and the user is prompted to "End Now?".   The Java process never exits, and the user must press either "End now" or "Cancel" buttons logout of Windows.

This problem occurs if the the Swing application is started using "javaw.exe".  If the application is started with "java.exe" then it exits normally.

This regression was introduced in 1.5.0_14.  We tested the same code (attached) on 1.5.0_13 and the problem does not occur and the program exits cleanly.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
  * Compile SwingTest code below
  * On Windows run: javaw.exe SwingTest    (NOTE: It is important that javaw.exe is used)
  * Wait for the Java frame to appear
  * Logout of Windows

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The windows logout completes without the "Not Responding" dialog appearing and the user pressing "End Now" or "Cancel".
ACTUAL -
The "Not Responding" dialog will appear and the logout process is halted.  The use must press "End Now" or "Cancel" to allow the logout to proceed.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
The standard windows "This program is not responding" dialog.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class SwingTest {
    public static void main(String... args) throws Exception {
        SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                JFrame frame = new JFrame("title");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
None known.  We had to revert to using older Java version.

Release Regression From : 5.0u13
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Comments
SUGGESTED FIX The previous version of the fix has one disadvantage: it will never delete "alive" components during log-off. A better version is available in jdk7: http://sa.sfbay.sun.com/projects/awt_data/7/6660258/ It simply calls ::DefWindowProc(WM_UNDOCUMNTED_CLIENTSHUTDOWN) without entering into self->WindowProc so as to avoid considering "self" as "alive" component in secondary message pump later.
19-01-2010

EVALUATION We shouldn't postpone component deletion during shutdown to terminate application conveniently. MSDN for WM_ENDSESSION: "The application need not call the DestroyWindow or PostQuitMessage function when the session is ending". So I believe that we may just skip component deletion and session will exit immediately.
19-02-2008

SUGGESTED FIX here's the diffs for jdk7: $ sccs diffs -C awt_Toolkit.h ------- awt_Toolkit.h ------- *** /tmp/sccs.sAA0eg 2008-02-19 12:14:51.000000000 +0300 --- awt_Toolkit.h 2008-02-18 14:04:10.000000000 +0300 *************** *** 387,392 **** --- 387,393 ---- BOOL m_verbose; BOOL m_isActive; // set to FALSE at beginning of Dispose BOOL m_isDisposed; // set to TRUE at end of Dispose + BOOL m_isSessionEnded; BOOL m_vmSignalled; // set to TRUE if QUERYENDSESSION has successfully // raised SIGTERM $ sccs diffs -C awt_Toolkit.cpp ------- awt_Toolkit.cpp ------- *** /tmp/sccs.vz1qMh 2008-02-19 12:15:16.000000000 +0300 --- awt_Toolkit.cpp 2008-02-18 15:26:01.000000000 +0300 *************** *** 331,336 **** --- 331,337 ---- m_verbose = FALSE; m_isActive = TRUE; m_isDisposed = FALSE; + m_isSessionEnded = FALSE; m_vmSignalled = FALSE; *************** *** 681,694 **** } case WM_AWT_DELETEOBJECT: { AwtObject *p = (AwtObject *)wParam; if (p->CanBeDeleted()) { // all the messages for this component are processed, so // it can be deleted delete p; ! } else { // postpone deletion, waiting for all the messages for this ! // component to be processed ! AwtToolkit::GetInstance().PostMessage(WM_AWT_DELETEOBJECT, wParam, (LPARAM)0); } return 0; } --- 682,698 ---- } case WM_AWT_DELETEOBJECT: { AwtObject *p = (AwtObject *)wParam; + AwtToolkit& tk = AwtToolkit::GetInstance(); + if (p->CanBeDeleted()) { // all the messages for this component are processed, so // it can be deleted delete p; ! } else if (!tk.m_isSessionEnded) { // postpone deletion, waiting for all the messages for this ! // component to be processed; skipping the deletion during ! // shutdown to exit gracefully (6660258) ! tk.PostMessage(WM_AWT_DELETEOBJECT, wParam, (LPARAM)0); } return 0; } *************** *** 936,941 **** --- 940,946 ---- // Keep pumping messages until the shutdown sequence halts the VM, // or we exit the MessageLoop because of a WM_QUIT message AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_isSessionEnded = TRUE; // if WM_QUERYENDSESSION hasn't successfully raised SIGTERM // we ignore the ENDSESSION message
19-02-2008

WORK AROUND 2. Use java.exe instead of javaw.exe With java.exe, we do not experience the issue you have reported. However, the java.exe will show the command prompt and direct all the sysout/syserr to the command prompt. User can run his/her application with redirection: $> java <app> >> sysout.txt Therefore, all the output will be directed to the sysout.txt file.
14-02-2008

WORK AROUND 1. Add -Xrs in Java runtime By adding the -Xrs flag, it reduces the OS signals used by JVM when shutting down an applications.
14-02-2008

EVALUATION There are special Windows messages that are sent to application when user chooses to end the session, these messages are WM_QUERYENDSESSION and WM_ENDSESSION. In response to the messages AWT initiates the shutdown procedure, in particular, it disposes the toolkit object and starts secondary message loop to delete the AWT components that weren't deleted before. In order to delete the objects there is custom WM_AWT_DELETEOBJECT message that is sent to the toolkit object and if the objects are ready to be deleted then the deletion will immediately happen. A component can't be deleted sometimes if the component handles another message. In this case, the WM_AWT_DELETEOBJECT message is posted to the toolkit object again to delete the component later. I'm running simple testcase (just an empty frame) using javaw.exe, then I'm trying to logout. The WM_[QUERY]ENDSESSION messages come to the toolkit object, as result of the WM_ENDSESSION message the toolkit thread enters into the secondary dispose loop and it never exit the loop. The only message I'm seeing in this loop is the WM_AWT_DELETEOBJECT message, the toolkit thread repeatedly tries to delete the component (frame) but the component handles another message. The message that the component handles has 0x003b identifier, it seems like this is MS undocumented message. The message is sent to application when user ends the session. The component just calls default window procedure for the message and then the default window procedure initiates the WM_QUERYENDSESSION, WM_ENDSESSION messages. In short, the toolkit thread repeatedly tries to dispose a component (in WndProc, WM_ENDSESSION) whereas the component handles MS shutdown message (waits in ::DefWindowProc that initiated the WM_ENDSESSION), this follows to the endless secondary loop.
13-02-2008

EVALUATION This bug is a regression of 6480378. If I delete the message loop introduced in this fix to AwtToolki::Dispose() method, javaw starts exiting correctly. I suspect this new problem is similar to what reported in 6513421.
08-02-2008

EVALUATION The problem can be reproduced only with javaw, not java, and only starting from 5.0u14. An interesting thing is that 7.0-b21 also has the same problem, but not 6uX.
08-02-2008