Update of /cvsroot/perl-win32-gui/Win32-GUI In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8818
Modified Files: CHANGELOG GUI_Events.cpp GUI_MessageLoops.cpp Log Message: Fix crashes when windows destroyed during callbacks to perl Index: CHANGELOG =================================================================== RCS file: /cvsroot/perl-win32-gui/Win32-GUI/CHANGELOG,v retrieving revision 1.113 retrieving revision 1.114 diff -C2 -d -r1.113 -r1.114 *** CHANGELOG 15 Jul 2007 18:39:51 -0000 1.113 --- CHANGELOG 15 Jul 2007 18:47:13 -0000 1.114 *************** *** 16,19 **** --- 16,21 ---- - DC.xs - Rework DrawFrameControl() to allow DFCS_ADJUSTRECT to modify input parameters + - GUI_Events.cpp, GUI_MessageLoops.cpp - handle window being destroyed in + callback by checking validity with IsWindow(hwnd) in many places + [Robert May] : 20 January 2007 - Restore Original WndProc Index: GUI_Events.cpp =================================================================== RCS file: /cvsroot/perl-win32-gui/Win32-GUI/GUI_Events.cpp,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** GUI_Events.cpp 3 Aug 2006 22:20:02 -0000 1.14 --- GUI_Events.cpp 15 Jul 2007 18:47:13 -0000 1.15 *************** *** 10,13 **** --- 10,26 ---- #include "GUI.h" + /* IMPORTANT: + * Whenever we make a callback into perl, we cannot know what evil things + * the script writer will have done. In particular, it is possible for + * the called code to cause the window for which the event is being + * handled to be destroyed before the callback returns. If this happens + * we will have a non-NULL perlud pointer, but the underlying memory + * will have been freed. Don't try to access perlud after a callback + * without checking that the window still exists. Currently the code + * below gets the window handle BEFORE the callback (from perud->svSelf), + * and checks it afterwards with IsWindow(). This is not infallable as the + * hwnd could have been recycled - this is, however, unlikely + */ + /* ########################################################################## *************** *** 47,50 **** --- 60,64 ---- int PerlResult = 1; + HWND hwnd = handle_From(NOTXSCALL perlud->svSelf); perlud->dwPlStyle &= ~PERLWIN32GUI_EVENTHANDLING; *************** *** 101,104 **** --- 115,120 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 163,166 **** --- 179,184 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 279,282 **** --- 297,301 ---- SV* acc_sub = NULL; int PerlResult = 1; + HWND hwnd = handle_From(NOTXSCALL perlud->svSelf); perlud->dwPlStyle &= ~PERLWIN32GUI_EVENTHANDLING; *************** *** 298,308 **** // Find for a child with AcceleratorName name if (strcmp (perlud->szWindowName, AcceleratorName) != 0) { - - HWND hWndParent = handle_From(NOTXSCALL perlud->svSelf); st_FindChildWindow st; st.perlchild = NULL; st.Name = AcceleratorName; ! EnumChildWindows(hWndParent, (WNDENUMPROC) FindChildWindowsProc, (LPARAM) &st); perlchild = st.perlchild; } --- 317,325 ---- // Find for a child with AcceleratorName name if (strcmp (perlud->szWindowName, AcceleratorName) != 0) { st_FindChildWindow st; st.perlchild = NULL; st.Name = AcceleratorName; ! EnumChildWindows(hwnd, (WNDENUMPROC) FindChildWindowsProc, (LPARAM) &st); perlchild = st.perlchild; } *************** *** 334,337 **** --- 351,356 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 363,366 **** --- 382,387 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 394,397 **** --- 415,420 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 426,429 **** --- 449,454 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 448,452 **** int count; int argtype; ! static char *textneeded = NULL; if(textneeded != NULL) { safefree(textneeded); --- 473,478 ---- int count; int argtype; ! HWND hwnd = handle_From(NOTXSCALL perlud->svSelf); ! static char *textneeded = NULL; /* XXX: Not Thread Safe */ if(textneeded != NULL) { safefree(textneeded); *************** *** 515,518 **** --- 541,546 ---- LEAVE; + if(!IsWindow(hwnd)) return textneeded; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 583,586 **** --- 611,616 ---- LEAVE; + if(!IsWindow(hwnd)) return textneeded; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 609,612 **** --- 639,643 ---- int PerlResult = 1; + HWND hwnd = handle_From(NOTXSCALL perlud->svSelf); perlud->dwPlStyle &= ~PERLWIN32GUI_EVENTHANDLING; *************** *** 674,677 **** --- 705,710 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 733,736 **** --- 766,771 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 758,761 **** --- 793,797 ---- SV** events = NULL; int PerlResult = 1; + HWND hwnd = handle_From(NOTXSCALL perlud->svSelf); perlud->dwPlStyle &= ~PERLWIN32GUI_EVENTHANDLING; *************** *** 829,832 **** --- 865,870 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 888,891 **** --- 926,931 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 906,909 **** --- 946,950 ---- SV* newdc; int PerlResult = 1; + HWND hwnd = handle_From(NOTXSCALL perlud->svSelf); perlud->dwPlStyle &= ~PERLWIN32GUI_EVENTHANDLING; *************** *** 949,952 **** --- 990,995 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; *************** *** 998,1001 **** --- 1041,1046 ---- LEAVE; + if(!IsWindow(hwnd)) return PerlResult; + // Must set after event call because this event can generate more event. perlud->dwPlStyle |= PERLWIN32GUI_EVENTHANDLING; Index: GUI_MessageLoops.cpp =================================================================== RCS file: /cvsroot/perl-win32-gui/Win32-GUI/GUI_MessageLoops.cpp,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** GUI_MessageLoops.cpp 16 Jul 2006 11:08:27 -0000 1.22 --- GUI_MessageLoops.cpp 15 Jul 2007 18:47:13 -0000 1.23 *************** *** 262,269 **** PerlResult = OnEvent[childud->iClass](NOTXSCALL childud, uMsg, wParam, lParam); ! if (childud->avHooks != NULL) DoHook(NOTXSCALL childud, (UINT) HIWORD(wParam), wParam, lParam, &PerlResult, WM_COMMAND); ! if(childud->forceResult != 0) { perlud->forceResult = childud->forceResult; childud->forceResult = 0; --- 262,269 ---- PerlResult = OnEvent[childud->iClass](NOTXSCALL childud, uMsg, wParam, lParam); ! if (IsWindow((HWND)lParam) && childud->avHooks != NULL) DoHook(NOTXSCALL childud, (UINT) HIWORD(wParam), wParam, lParam, &PerlResult, WM_COMMAND); ! if(IsWindow((HWND)lParam) && childud->forceResult != 0) { perlud->forceResult = childud->forceResult; childud->forceResult = 0; *************** *** 328,335 **** } ! if (childud->avHooks != NULL) DoHook(NOTXSCALL childud, (UINT) (((LPNMHDR) lParam)->code), wParam, lParam, &PerlResult, WM_NOTIFY); ! if(childud->forceResult != 0) { perlud->forceResult = childud->forceResult; childud->forceResult = 0; --- 328,335 ---- } ! if (IsWindow(((LPNMHDR)lParam)->hwndFrom) && childud->avHooks != NULL) DoHook(NOTXSCALL childud, (UINT) (((LPNMHDR) lParam)->code), wParam, lParam, &PerlResult, WM_NOTIFY); ! if (IsWindow(((LPNMHDR)lParam)->hwndFrom) && childud->forceResult != 0) { perlud->forceResult = childud->forceResult; childud->forceResult = 0; *************** *** 654,658 **** // Hook processing ! if(perlud->avHooks != NULL) { DoHook(NOTXSCALL perlud, uMsg, wParam, lParam, &PerlResult,0); } --- 654,658 ---- // Hook processing ! if(IsWindow(hwnd) && perlud->avHooks != NULL) { DoHook(NOTXSCALL perlud, uMsg, wParam, lParam, &PerlResult,0); } *************** *** 660,669 **** // Default processing if(PerlResult == -1) { ! PostMessage(hwnd, WM_EXITLOOP, (WPARAM) -1, 0); PerlResult = 0; ! } else if (PerlResult != 0) { PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam, perlud->WndProc); } ! else if (perlud->forceResult != 0) { return perlud->forceResult; } --- 660,673 ---- // Default processing if(PerlResult == -1) { ! if(IsWindow(hwnd)) { ! PostMessage(hwnd, WM_EXITLOOP, (WPARAM) -1, 0); ! } else { ! PostThreadMessage(GetCurrentThreadId(), WM_EXITLOOP, (WPARAM) -1, 0); ! } PerlResult = 0; ! } else if (IsWindow(hwnd) && PerlResult != 0) { PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam, perlud->WndProc); } ! else if (IsWindow(hwnd) && perlud->forceResult != 0) { return perlud->forceResult; } *************** *** 996,1007 **** } ! if (perlud->avHooks != NULL) DoHook(NOTXSCALL perlud, uMsg,wParam,lParam,&PerlResult,0); ! ! if (PerlResult != 0) { PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam, perlud->WndProc); } ! else if ( perlud->forceResult != 0) { return perlud->forceResult; } --- 1000,1010 ---- } ! if (IsWindow(hwnd) && perlud->avHooks != NULL) DoHook(NOTXSCALL perlud, uMsg,wParam,lParam,&PerlResult,0); ! if (IsWindow(hwnd) && PerlResult != 0) { PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam, perlud->WndProc); } ! else if (IsWindow(hwnd) && perlud->forceResult != 0) { return perlud->forceResult; } *************** *** 1102,1109 **** // Hook for non interactive control ! if (perlud->avHooks != NULL && !(perlud->dwPlStyle & PERLWIN32GUI_INTERACTIVE)) DoHook(NOTXSCALL perlud, uMsg,wParam,lParam,&PerlResult,0); ! if (PerlResult != 0) { // If interactive control, call ControlMsgLoop if (perlud->dwPlStyle & PERLWIN32GUI_INTERACTIVE) --- 1105,1112 ---- // Hook for non interactive control ! if (IsWindow(hwnd) && perlud->avHooks != NULL && !(perlud->dwPlStyle & PERLWIN32GUI_INTERACTIVE)) DoHook(NOTXSCALL perlud, uMsg,wParam,lParam,&PerlResult,0); ! if (IsWindow(hwnd) && PerlResult != 0) { // If interactive control, call ControlMsgLoop if (perlud->dwPlStyle & PERLWIN32GUI_INTERACTIVE) *************** *** 1112,1116 **** PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam, perlud->WndProc); } ! else if (perlud->forceResult != 0) { return perlud->forceResult; } --- 1115,1119 ---- PerlResult = CommonMsgLoop(NOTXSCALL hwnd, uMsg, wParam, lParam, perlud->WndProc); } ! else if (IsWindow(hwnd) && perlud->forceResult != 0) { return perlud->forceResult; }