#17884: Application crash on system restart/shutdown on Windows 7

66 views
Skip to first unread message

wxTrac

unread,
Jun 7, 2017, 7:16:03 AM6/7/17
to wx-...@googlegroups.com
#17884: Application crash on system restart/shutdown on Windows 7
-------------------------------+--------------------
Reporter: feng1 | Owner:
Type: defect | Status: new
Priority: normal | Milestone:
Component: wxMSW | Version: 3.1.0
Keywords: wxWindowMSW crash | Blocked By:
Blocking: | Patch: 0
-------------------------------+--------------------
How to reproduce:
1. Open up Notepad and type something in there. The unsaved document
confirmation message of Notepad will prevent your system from rebooting.
2. Build and run the <wxdir>\samples\dialogs sample.
3. Choose Dialogs->Message box in the menu.
4. Trigger system restart.
5. Application crashes.

The crash always happens on Windows 7 x64, but never does on Windows 10
x64. Happens in debug and release builds. If step 3 is omitted, the crash
happens sometimes but not always on Windows 7 x64.

Application crashes at <wxdir>\src\msw\window.cpp in method "LRESULT
WXDLLEXPORT APIENTRY
wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)" - line
2667 with an access violation:
{{{
wxSEH_TRY
{
if ( wnd && wxGUIEventLoop::AllowProcessing(wnd) )
--> rc = wnd->MSWWindowProc(message, wParam, lParam);
else
rc = ::DefWindowProc(hWnd, message, wParam, lParam);
}
}}}
wnd is pointing at a deleted element.


While trying to fix the problem myself, I tried to just send the
WM_QUERYENDSESSION message, which Windows sends to all applications on
restart/shutdown, from another application to the running sample. This
never caused a crash. The app closed gracefully.
{{{
#include <Windows.h>
void main() {
HWND hWnd = FindWindow(NULL, "wxWidgets dialogs example");
if (hWnd) {
PostMessage(hWnd, WM_QUERYENDSESSION, 0, ENDSESSION_CLOSEAPP);
}
}
}}}

--
Ticket URL: <http://trac.wxwidgets.org/ticket/17884>

wxTrac

unread,
Jun 7, 2017, 8:51:53 AM6/7/17
to wx-...@googlegroups.com
#17884: Application crash on system restart/shutdown on Windows 7
---------------------+-------------------------------
Reporter: feng1 | Owner:
Type: defect | Status: new
Priority: normal | Milestone:
Component: wxMSW | Version: 3.1.0
Resolution: | Keywords: wxWindowMSW crash
Blocked By: | Blocking:
Patch: 0 |
---------------------+-------------------------------

Comment (by vadz):

Did you see which message was being processed when it crashed? And any
idea what window could it have been? Even if it's already destroyed, you
can often make a guess about its kind, e.g. by looking at the stack (could
you please also post it here BTW?).

--
Ticket URL: <http://trac.wxwidgets.org/ticket/17884#comment:1>

wxTrac

unread,
Jun 7, 2017, 10:01:18 AM6/7/17
to wx-...@googlegroups.com
#17884: Application crash on system restart/shutdown on Windows 7
---------------------+-------------------------------
Reporter: feng1 | Owner:
Type: defect | Status: new
Priority: normal | Milestone:
Component: wxMSW | Version: 3.1.0
Resolution: | Keywords: wxWindowMSW crash
Blocked By: | Blocking:
Patch: 0 |
---------------------+-------------------------------

Comment (by feng1):

The message is WM_ACTIVATEAPP.
The deleted window is the main frame itself (MyFrame : wxFrame).

Call stack:
{{{
> dialogs.exe!wxWndProc(HWND__ * hWnd, unsigned int message,
unsigned __int64 wParam, __int64 lParam) Line 2665 C++
[External Code]
dialogs.exe!wxToolTip::DeleteToolTipCtrl() Line 286 C++
dialogs.exe!wxToolTipModule::OnExit() Line 154 C++
dialogs.exe!wxModule::Exit() Line 41 C++
dialogs.exe!wxModule::DoCleanUpModules(const wxModuleList &
modules) Line 197 C++
dialogs.exe!wxModule::CleanUpModules() Line 57 C++
dialogs.exe!DoCommonPostCleanup() Line 415 C++
dialogs.exe!wxEntryCleanup() Line 459 C++
dialogs.exe!wxApp::OnEndSession(wxCloseEvent & __formal) Line 783
C++
dialogs.exe!wxAppConsoleBase::HandleEvent(wxEvtHandler * handler,
void(wxEvtHandler::*)(wxEvent &) func, wxEvent & event) Line 658 C++
dialogs.exe!wxAppConsoleBase::CallEventHandler(wxEvtHandler *
handler, wxEventFunctor & functor, wxEvent & event) Line 670 C++
dialogs.exe!wxEvtHandler::ProcessEventIfMatchesId(const
wxEventTableEntryBase & entry, wxEvtHandler * handler, wxEvent & event)
Line 1383 C++
dialogs.exe!wxEventHashTable::HandleEvent(wxEvent & event,
wxEvtHandler * self) Line 989 C++
dialogs.exe!wxEvtHandler::TryHereOnly(wxEvent & event) Line 1578
C++
dialogs.exe!wxEvtHandler::TryBeforeAndHere(wxEvent & event) Line
3656 C++
dialogs.exe!wxEvtHandler::ProcessEventLocally(wxEvent & event)
Line 1511 C++
dialogs.exe!wxEvtHandler::ProcessEvent(wxEvent & event) Line 1484
C++
dialogs.exe!wxWindow::HandleEndSession(bool endSession, long
logOff) Line 3880 C++
dialogs.exe!wxWindow::MSWHandleMessage(__int64 * result, unsigned
int message, unsigned __int64 wParam, __int64 lParam) Line 3219 C++
dialogs.exe!wxWindow::MSWWindowProc(unsigned int message, unsigned
__int64 wParam, __int64 lParam) Line 3522 C++
dialogs.exe!wxTopLevelWindowMSW::MSWWindowProc(unsigned int
message, unsigned __int64 wParam, __int64 lParam) Line 321 C++
dialogs.exe!wxFrame::MSWWindowProc(unsigned int message, unsigned
__int64 wParam, __int64 lParam) Line 897 C++
dialogs.exe!wxWndProc(HWND__ * hWnd, unsigned int message,
unsigned __int64 wParam, __int64 lParam) Line 2665 C++
[External Code]
dialogs.exe!wxMessageDialog::ShowModal() Line 559 C++
dialogs.exe!MyFrame::MessageBoxW(wxCommandEvent & __formal) Line
884 C++
dialogs.exe!wxAppConsoleBase::HandleEvent(wxEvtHandler * handler,
void(wxEvtHandler::*)(wxEvent &) func, wxEvent & event) Line 658 C++
dialogs.exe!wxAppConsoleBase::CallEventHandler(wxEvtHandler *
handler, wxEventFunctor & functor, wxEvent & event) Line 670 C++
dialogs.exe!wxEvtHandler::ProcessEventIfMatchesId(const
wxEventTableEntryBase & entry, wxEvtHandler * handler, wxEvent & event)
Line 1383 C++
dialogs.exe!wxEventHashTable::HandleEvent(wxEvent & event,
wxEvtHandler * self) Line 989 C++
dialogs.exe!wxEvtHandler::TryHereOnly(wxEvent & event) Line 1578
C++
dialogs.exe!wxEvtHandler::TryBeforeAndHere(wxEvent & event) Line
3656 C++
dialogs.exe!wxEvtHandler::ProcessEventLocally(wxEvent & event)
Line 1511 C++
dialogs.exe!wxEvtHandler::ProcessEvent(wxEvent & event) Line 1484
C++
dialogs.exe!wxWindowBase::TryAfter(wxEvent & event) Line 3457
C++
dialogs.exe!wxEvtHandler::ProcessEvent(wxEvent & event) Line 1497
C++
dialogs.exe!wxEvtHandler::SafelyProcessEvent(wxEvent & event) Line
1602 C++
dialogs.exe!wxWindowBase::HandleWindowEvent(wxEvent & event) Line
1535 C++
dialogs.exe!wxMenuBase::DoProcessEvent(wxMenuBase * menu, wxEvent
& event, wxWindow * win) Line 673 C++
dialogs.exe!wxMenuBase::SendEvent(int itemid, int checked) Line
643 C++
dialogs.exe!wxFrameBase::ProcessCommand(wxMenuItem * item) Line
295 C++
dialogs.exe!wxFrame::HandleCommand(unsigned short id, unsigned
short cmd, HWND__ * control) Line 799 C++
dialogs.exe!wxFrame::MSWWindowProc(unsigned int message, unsigned
__int64 wParam, __int64 lParam) Line 856 C++
dialogs.exe!wxWndProc(HWND__ * hWnd, unsigned int message,
unsigned __int64 wParam, __int64 lParam) Line 2665 C++
[External Code]
dialogs.exe!wxGUIEventLoop::ProcessMessage(tagMSG * msg) Line 169
C++
dialogs.exe!wxGUIEventLoop::Dispatch() Line 229 C++
dialogs.exe!wxEventLoopManual::ProcessEvents() Line 228 C++
dialogs.exe!wxEventLoopManual::DoRun() Line 273 C++
dialogs.exe!wxEventLoopBase::Run() Line 76 C++
dialogs.exe!wxAppConsoleBase::MainLoop() Line 380 C++
dialogs.exe!wxAppConsoleBase::OnRun() Line 302 C++
dialogs.exe!wxAppBase::OnRun() Line 312 C++
dialogs.exe!wxEntryReal(int & argc, wchar_t * * argv) Line 503
C++
dialogs.exe!wxEntry(int & argc, wchar_t * * argv) Line 181
C++
dialogs.exe!wxEntry(HINSTANCE__ * hInstance, HINSTANCE__ *
__formal, char * __formal, int nCmdShow) Line 290 C++
dialogs.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ *
hPrevInstance, char * __formal, int nCmdShow) Line 129 C++
[External Code]
}}}

Locals:
{{{
Name Value Type
hWnd 0x00000000002e0a1e {unused=-572662307 } HWND__ *
lParam 1676 __int64
message 28 unsigned int
rc 0 __int64
wnd 0x00000000002f3520 {m_hWnd=0xdddddddddddddddd {unused=??? }
m_oldWndProc=0xdddddddddddddddd m_mouseInWindow=...} wxWindow *
wParam 0 unsigned __int64
}}}

Debug output after restart was triggered:
{{{
..\..\src\msw\app.cpp(692): 'UnregisterClass(wxWindowNR)' failed with
error 0x00000584 (class still has open windows.).
Exception thrown: read access violation.
wnd-> was 0xFFFFFFFFFFFFF9D7.
}}}

--
Ticket URL: <http://trac.wxwidgets.org/ticket/17884#comment:2>

wxTrac

unread,
Jun 7, 2017, 10:11:41 AM6/7/17
to wx-...@googlegroups.com
#17884: Application crash on system restart/shutdown on Windows 7
---------------------+-------------------------------
Reporter: feng1 | Owner:
Type: defect | Status: confirmed
Priority: normal | Milestone:
Component: wxMSW | Version: 3.1.0
Resolution: | Keywords: wxWindowMSW crash
Blocked By: | Blocking:
Patch: 0 |
---------------------+-------------------------------
Changes (by vadz):

* status: new => confirmed


Comment:

Thanks! The problem is clearly that the frame is deleted while the modal
dialog is shown and from inside its modal loop. We must either not let
this happen (but we could still get closed forcefully by Windows?) or
close the dialog(s) first. I don't know what would actually be better,
could you please check how does Notepad itself behave? I.e. if you try to
close it, so that it displays the dialog about unsaved changes and then
try to shutdown, what happens? My guess would be that Notepad is brought
into foreground allowing you to answer the dialog, but I have no idea what
happens next...

--
Ticket URL: <http://trac.wxwidgets.org/ticket/17884#comment:3>

wxTrac

unread,
Jun 8, 2017, 4:33:13 AM6/8/17
to wx-...@googlegroups.com
#17884: Application crash on system restart/shutdown on Windows 7
---------------------+-------------------------------
Reporter: feng1 | Owner:
Type: defect | Status: confirmed
Priority: normal | Milestone:
Component: wxMSW | Version: 3.1.0
Resolution: | Keywords: wxWindowMSW crash
Blocked By: | Blocking:
Patch: 0 |
---------------------+-------------------------------

Comment (by feng1):

Setup: Notepad is open, something unsaved is typed in.
Case 1: No dialog open yet. Restart triggered.
Case 2: Unsaved document dialog is open. Restart triggered.

Case 1:
1. Windows sends WM_QUERYENDSESSION (wparam 0, lparam 0).
2. Notepad does not answer with TRUE to this message.
3. Dialog pops up and the notepad frame starts sending
WM_ENTERIDLE (wparam: MSGF_DIALOGBOX, lparam: hwnd of dialog box) around
every second.
4. Then after a few seconds Windows blurs the screen with its own
info, that the restart is being blocked by this and that application with
options to forcefully restart the system.

Case 2 is handled differently:
1. Windows sends WM_QUERYENDSESSION (wparam 0, lparam 0) to both
handles, the notepad frame and the dialog.
2. Notepad still does not answer it, but the dialog does. The
dialog returns TRUE, which means ShutdownIsOk.
3. But Notepad or the dialog, I cannot see the offspring, create
another dialog on top. So that there is the Notepad frame, the unsaved
document dialog and the new one.
4. The new dialog is attached as screenshot. It says:
"You cannot shut down or log off Windows because the Save
As dialog box in Notepad is open. Switch to Notepad, close this dialog
box, and then try shutting down or logging off Windows again."

Case 3 (restart with the new dialog box open):
1. Same as Case 2, but the new dialog is opened up another time,
so you have two of it.



But please keep the following in mind:
I was able to reproduce the crash even if there was no dialog box
open in the first place. It just is not consistent. Means, I start the
dialogs sample without opening any dialog boxes and trigger the restart.
The application crashes irregularly. I also encountered this issue with my
own application, when I introduced wxRichToolTip to a certain frame. As
long as this frame was never loaded, there were irregular crashes. As soon
as I opened that frame up and tried to restart, the crash always came.

I don't want to lead you to wrong assumptions, but when I was
trying to fix it, I updated the mentioned window.cpp so it wrote the
pointers and HWND of each window to the debug output on creation and
deletion.
Every window was deleted correctly and in correct order in the
crash and the non-crash case. I suggest, that there is a race condition,
where the WM_ACTIVATEAPP is being handled while its frame is being deleted
at the same time.

I couldn't analyze it further, because as soon as I was debugging
and thus blocking the message processing, the crash was prevented.

--
Ticket URL: <http://trac.wxwidgets.org/ticket/17884#comment:4>
Reply all
Reply to author
Forward
0 new messages