提交 5fadc98d 编写于 作者: B bagiras

7073337: Crash after playing Java game on Pogo

Reviewed-by: art, uta
上级 a258c6e6
......@@ -615,6 +615,14 @@ public abstract class WComponentPeer extends WObjectPeer
_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());
......
......@@ -183,6 +183,7 @@ jmethodID AwtComponent::isEnabledMID;
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 @@ AwtComponent::AwtComponent()
m_hCursorCache = NULL;
m_bSubclassed = FALSE;
m_bPauseDestroy = FALSE;
m_MessagesProcessing = 0;
m_wheelRotationAmount = 0;
......@@ -319,6 +321,12 @@ void AwtComponent::Dispose()
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 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
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 @@ LRESULT AwtComponent::DefWindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
*/
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 @@ Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls)
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 @@ Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls)
DASSERT(AwtComponent::getLocationOnScreenMID);
DASSERT(AwtComponent::replaceSurfaceDataMID);
DASSERT(AwtComponent::replaceSurfaceDataLaterMID);
DASSERT(AwtComponent::disposeLaterMID);
CATCH_BAD_ALLOC;
}
......
......@@ -119,6 +119,7 @@ public:
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 @@ public:
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 @@ public:
return m_MessagesProcessing == 0;
}
BOOL IsDestroyPaused() const {
return m_bPauseDestroy;
}
protected:
static AwtComponent* GetComponentImpl(HWND hWnd);
......@@ -752,6 +758,7 @@ private:
UINT m_mouseButtonClickAllowed;
BOOL m_bSubclassed;
BOOL m_bPauseDestroy;
COLORREF m_colorForeground;
COLORREF m_colorBackground;
......
......@@ -733,26 +733,13 @@ LRESULT CALLBACK AwtToolkit::WndProc(HWND hWnd, UINT message,
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,27 +1327,48 @@ BOOL AwtToolkit::PumpWaitingMessages(PEEKMESSAGEPROC lpPeekMessageFunc)
while (!m_breakMessageLoop && (*lpPeekMessageFunc)(msg)) {
foundOne = TRUE;
if (msg.message == WM_QUIT) {
m_breakMessageLoop = TRUE;
m_messageLoopResult = static_cast<UINT>(msg.wParam);
if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS)
::PostQuitMessage(static_cast<int>(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);
}
}
}
void AwtToolkit::ProcessMsg(MSG& msg)
{
if (msg.message == WM_QUIT) {
m_breakMessageLoop = TRUE;
m_messageLoopResult = static_cast<UINT>(msg.wParam);
if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS)
::PostQuitMessage(static_cast<int>(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
AwtToolkit::PrimaryIdleFunc() {
AwtToolkit::SetBusy(FALSE);
......
......@@ -305,6 +305,8 @@ public:
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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册