Add a test of throwing an exception from wxYield() to except sample.

This demonstrates that under 64 bit Windows exceptions may not propagate
through the kernel code and throwing from inside wxYield() results in either
an immediate abort, even if the code calling wxYield() tries to handle the
exception, or, even more surprisingly, is just completely ignored.

See http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/
for more information.

Moreover, independently of Windows weirdness, throwing from wxYield() also
results in a difficult to debug crash when using wxGTK because C++ exceptions
can't propagate through C GTK+ code in this case.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@77465 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2014-08-24 15:31:33 +00:00
parent 3e2a7cca72
commit b133193aa3

View File

@@ -47,6 +47,8 @@
#include "wx/thread.h"
#endif
#include "wx/uiaction.h"
// ----------------------------------------------------------------------------
// resources
// ----------------------------------------------------------------------------
@@ -117,6 +119,7 @@ public:
void OnThrowString(wxCommandEvent& event);
void OnThrowObject(wxCommandEvent& event);
void OnThrowUnhandled(wxCommandEvent& event);
void OnThrowFromYield(wxCommandEvent& event);
void OnCrash(wxCommandEvent& event);
void OnTrap(wxCommandEvent& event);
@@ -187,6 +190,7 @@ enum
Except_ThrowString,
Except_ThrowObject,
Except_ThrowUnhandled,
Except_ThrowFromYield,
Except_Crash,
Except_Trap,
#if wxUSE_ON_FATAL_EXCEPTION
@@ -217,6 +221,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Except_ThrowString, MyFrame::OnThrowString)
EVT_MENU(Except_ThrowObject, MyFrame::OnThrowObject)
EVT_MENU(Except_ThrowUnhandled, MyFrame::OnThrowUnhandled)
EVT_MENU(Except_ThrowFromYield, MyFrame::OnThrowFromYield)
EVT_MENU(Except_Crash, MyFrame::OnCrash)
EVT_MENU(Except_Trap, MyFrame::OnTrap)
#if wxUSE_ON_FATAL_EXCEPTION
@@ -354,6 +359,8 @@ MyFrame::MyFrame()
menuFile->Append(Except_ThrowObject, wxT("Throw an &object\tCtrl-O"));
menuFile->Append(Except_ThrowUnhandled,
wxT("Throw &unhandled exception\tCtrl-U"));
menuFile->Append(Except_ThrowFromYield,
wxT("Throw from wx&Yield()\tCtrl-Y"));
menuFile->Append(Except_Crash, wxT("&Crash\tCtrl-C"));
menuFile->Append(Except_Trap, "&Trap\tCtrl-T",
"Break into the debugger (if one is running)");
@@ -446,6 +453,29 @@ void MyFrame::OnThrowUnhandled(wxCommandEvent& WXUNUSED(event))
throw UnhandledException();
}
void MyFrame::OnThrowFromYield(wxCommandEvent& WXUNUSED(event))
{
#if wxUSE_UIACTIONSIMULATOR
// Simulate selecting the "Throw unhandled" menu item, its handler will be
// executed from inside wxYield(), so we may not be able to catch the
// exception here under Win64 even in spite of an explicit catch.
try
{
wxUIActionSimulator sim;
sim.Char('U', wxMOD_CONTROL);
wxYield();
}
catch ( UnhandledException& )
{
wxLogMessage("Caught unhandled exception inside wxYield().");
}
#else // !wxUSE_UIACTIONSIMULATOR
wxLogError("Can't trigger an exception inside wxYield() "
"without wxUIActionSimulator, please rebuild "
"with wxUSE_UIACTIONSIMULATOR=1.");
#endif // wxUSE_UIACTIONSIMULATOR/!wxUSE_UIACTIONSIMULATOR
}
void MyFrame::OnCrash(wxCommandEvent& WXUNUSED(event))
{
DoCrash();