United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6660258 Java application stops Windows logout/shutdown (regression in 1.5.0_14)
JDK-6660258 : Java application stops Windows logout/shutdown (regression in 1.5.0_14)

Details
Type:
Bug
Submit Date:
2008-02-07
Status:
Closed
Updated Date:
2013-09-12
Project Name:
JDK
Resolved Date:
2009-12-03
Component:
client-libs
OS:
windows_xp
Sub-Component:
java.awt
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
5.0
Fixed Versions:
5.0u23 (b01)

Related Reports
Backport:
Backport:
Backport:
Backport:
Duplicate:
Relates:
Relates:

Sub Tasks

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
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.
                                     
2008-02-08
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.
                                     
2008-02-08
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.
                                     
2008-02-14
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
                                     
2008-02-19
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.
                                     
2008-02-19
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.
                                     
2010-01-19
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.
                                     
2008-02-13
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.
                                     
2008-02-14



Hardware and Software, Engineered to Work Together