# HG changeset patch # User bagiras # Date 1317116309 -14400 # Node ID 080571e66cc612cf0637843b450b819612ea0f35 # Parent 120c7e8ab07df3e232b689d45eea82f62bc9db5c 7073337: Crash after playing Java game on Pogo Reviewed-by: art, uta diff -r 120c7e8ab07d -r 080571e66cc6 jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java --- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Mon Sep 26 15:40:05 2011 -0700 +++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Tue Sep 27 13:38:29 2011 +0400 @@ -615,6 +615,14 @@ _dispose(); } + public void disposeLater() { + postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), new Runnable() { + public void run() { + dispose(); + } + })); + } + public synchronized void setForeground(Color c) { foreground = c; _setForeground(c.getRGB()); diff -r 120c7e8ab07d -r 080571e66cc6 jdk/src/windows/native/sun/windows/awt_Component.cpp --- a/jdk/src/windows/native/sun/windows/awt_Component.cpp Mon Sep 26 15:40:05 2011 -0700 +++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp Tue Sep 27 13:38:29 2011 +0400 @@ -183,6 +183,7 @@ jmethodID AwtComponent::getLocationOnScreenMID; jmethodID AwtComponent::replaceSurfaceDataMID; jmethodID AwtComponent::replaceSurfaceDataLaterMID; +jmethodID AwtComponent::disposeLaterMID; HKL AwtComponent::m_hkl = ::GetKeyboardLayout(0); LANGID AwtComponent::m_idLang = LOWORD(::GetKeyboardLayout(0)); @@ -246,6 +247,7 @@ m_hCursorCache = NULL; m_bSubclassed = FALSE; + m_bPauseDestroy = FALSE; m_MessagesProcessing = 0; m_wheelRotationAmount = 0; @@ -319,6 +321,12 @@ m_brushBackground = NULL; } + if (m_bPauseDestroy) { + // AwtComponent::WmNcDestroy could be released now + m_bPauseDestroy = FALSE; + m_hwnd = NULL; + } + // The component instance is deleted using AwtObject::Dispose() method AwtObject::Dispose(); } @@ -1377,6 +1385,7 @@ case WM_CREATE: mr = WmCreate(); break; case WM_CLOSE: mr = WmClose(); break; case WM_DESTROY: mr = WmDestroy(); break; + case WM_NCDESTROY: mr = WmNcDestroy(); break; case WM_ERASEBKGND: mr = WmEraseBkgnd((HDC)wParam, *(BOOL*)&retValue); break; @@ -1965,10 +1974,24 @@ */ MsgRouting AwtComponent::WmDestroy() { - // fix for 6259348: we should enter the SyncCall critical section before - // disposing the native object, that is value 1 of lParam is intended for - if(m_peerObject != NULL) { // is not being terminating - AwtToolkit::GetInstance().SendMessage(WM_AWT_DISPOSE, (WPARAM)m_peerObject, (LPARAM)1); + return mrConsume; +} + +/* + * This message should only be received when a window is destroyed by + * Windows, and not Java. It is sent only after child windows were destroyed. + */ +MsgRouting AwtComponent::WmNcDestroy() +{ + if (m_peerObject != NULL) { // is not being terminating + // Stay in this handler until AwtComponent::Dispose is called. + m_bPauseDestroy = TRUE; + + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + // Post invocation event for WObjectPeer.dispose to EDT + env->CallVoidMethod(m_peerObject, AwtComponent::disposeLaterMID); + // Wait until AwtComponent::Dispose is called + AwtToolkit::GetInstance().PumpToDestroy(this); } return mrConsume; @@ -6300,6 +6323,7 @@ env->GetMethodID(peerCls, "replaceSurfaceData", "()V"); AwtComponent::replaceSurfaceDataLaterMID = env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V"); + AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V"); DASSERT(AwtComponent::xID); DASSERT(AwtComponent::yID); @@ -6318,6 +6342,8 @@ DASSERT(AwtComponent::getLocationOnScreenMID); DASSERT(AwtComponent::replaceSurfaceDataMID); DASSERT(AwtComponent::replaceSurfaceDataLaterMID); + DASSERT(AwtComponent::disposeLaterMID); + CATCH_BAD_ALLOC; } diff -r 120c7e8ab07d -r 080571e66cc6 jdk/src/windows/native/sun/windows/awt_Component.h --- a/jdk/src/windows/native/sun/windows/awt_Component.h Mon Sep 26 15:40:05 2011 -0700 +++ b/jdk/src/windows/native/sun/windows/awt_Component.h Tue Sep 27 13:38:29 2011 +0400 @@ -119,6 +119,7 @@ static jmethodID getLocationOnScreenMID; static jmethodID replaceSurfaceDataMID; static jmethodID replaceSurfaceDataLaterMID; + static jmethodID disposeLaterMID; static const UINT WmAwtIsComponent; static jint * masks; //InputEvent mask array @@ -490,6 +491,7 @@ virtual MsgRouting WmCreate() {return mrDoDefault;} virtual MsgRouting WmClose() {return mrDoDefault;} virtual MsgRouting WmDestroy(); + virtual MsgRouting WmNcDestroy(); virtual MsgRouting WmActivate(UINT nState, BOOL fMinimized, HWND opposite) { @@ -711,6 +713,10 @@ return m_MessagesProcessing == 0; } + BOOL IsDestroyPaused() const { + return m_bPauseDestroy; + } + protected: static AwtComponent* GetComponentImpl(HWND hWnd); @@ -752,6 +758,7 @@ UINT m_mouseButtonClickAllowed; BOOL m_bSubclassed; + BOOL m_bPauseDestroy; COLORREF m_colorForeground; COLORREF m_colorBackground; diff -r 120c7e8ab07d -r 080571e66cc6 jdk/src/windows/native/sun/windows/awt_Toolkit.cpp --- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Mon Sep 26 15:40:05 2011 -0700 +++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Tue Sep 27 13:38:29 2011 +0400 @@ -733,26 +733,13 @@ return 0; } case WM_AWT_DISPOSE: { - BOOL canDispose = TRUE; - CriticalSection &syncCS = AwtToolkit::GetInstance().GetSyncCS(); - int shouldEnterCriticalSection = (int)lParam; - if (shouldEnterCriticalSection == 1) { - canDispose = syncCS.TryEnter(); - } - if (canDispose) { - if(wParam != NULL) { - jobject self = (jobject)wParam; - AwtObject *o = (AwtObject *) JNI_GET_PDATA(self); - env->DeleteGlobalRef(self); - if(o != NULL && theAwtObjectList.Remove(o)) { - o->Dispose(); - } - if (shouldEnterCriticalSection) { - syncCS.Leave(); - } + if(wParam != NULL) { + jobject self = (jobject)wParam; + AwtObject *o = (AwtObject *) JNI_GET_PDATA(self); + env->DeleteGlobalRef(self); + if(o != NULL && theAwtObjectList.Remove(o)) { + o->Dispose(); } - } else { - AwtToolkit::GetInstance().PostMessage(WM_AWT_DISPOSE, wParam, lParam); } return 0; } @@ -1340,25 +1327,46 @@ while (!m_breakMessageLoop && (*lpPeekMessageFunc)(msg)) { foundOne = TRUE; - if (msg.message == WM_QUIT) { - m_breakMessageLoop = TRUE; - m_messageLoopResult = static_cast(msg.wParam); - if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS) - ::PostQuitMessage(static_cast(msg.wParam)); // make sure all loops exit - break; - } - else if (msg.message != WM_NULL) { - /* - * The AWT in standalone mode (that is, dynamically loaded from the - * Java VM) doesn't have any translation tables to worry about, so - * TranslateAccelerator isn't called. - */ - - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); + ProcessMsg(msg); + } + return foundOne; +} + +void AwtToolkit::PumpToDestroy(class AwtComponent* p) +{ + MSG msg; + + DASSERT(AwtToolkit::PrimaryIdleFunc != NULL); + DASSERT(AwtToolkit::CommonPeekMessageFunc != NULL); + + while (p->IsDestroyPaused() && !m_breakMessageLoop) { + + PrimaryIdleFunc(); + + while (p->IsDestroyPaused() && !m_breakMessageLoop && CommonPeekMessageFunc(msg)) { + ProcessMsg(msg); } } - return foundOne; +} + +void AwtToolkit::ProcessMsg(MSG& msg) +{ + if (msg.message == WM_QUIT) { + m_breakMessageLoop = TRUE; + m_messageLoopResult = static_cast(msg.wParam); + if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS) + ::PostQuitMessage(static_cast(msg.wParam)); // make sure all loops exit + } + else if (msg.message != WM_NULL) { + /* + * The AWT in standalone mode (that is, dynamically loaded from the + * Java VM) doesn't have any translation tables to worry about, so + * TranslateAccelerator isn't called. + */ + + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } } VOID CALLBACK diff -r 120c7e8ab07d -r 080571e66cc6 jdk/src/windows/native/sun/windows/awt_Toolkit.h --- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h Mon Sep 26 15:40:05 2011 -0700 +++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h Tue Sep 27 13:38:29 2011 +0400 @@ -305,6 +305,8 @@ UINT MessageLoop(IDLEPROC lpIdleFunc, PEEKMESSAGEPROC lpPeekMessageFunc); BOOL PumpWaitingMessages(PEEKMESSAGEPROC lpPeekMessageFunc); + void PumpToDestroy(class AwtComponent* p); + void ProcessMsg(MSG& msg); BOOL PreProcessMsg(MSG& msg); BOOL PreProcessMouseMsg(class AwtComponent* p, MSG& msg); BOOL PreProcessKeyMsg(class AwtComponent* p, MSG& msg);