Factor out exception handling code in a new WXConsumeException()

This will allow using this code from other places and not only when executing
user-defined event handlers.

No changes in this commit yet.
This commit is contained in:
Vadim Zeitlin
2016-11-15 00:55:08 +01:00
parent fd9e71afb7
commit 239469457d
2 changed files with 67 additions and 46 deletions

View File

@@ -3386,6 +3386,18 @@ public:
// NOTE: uses AddPendingEvent(); call only from secondary threads // NOTE: uses AddPendingEvent(); call only from secondary threads
#endif #endif
#if wxUSE_EXCEPTIONS
// This is a private function which handles any exceptions arising during
// the execution of user-defined code called in the event loop context by
// forwarding them to wxApp::OnExceptionInMainLoop() and, if it rethrows,
// to wxApp::OnUnhandledException(). In any case this function ensures that
// no exceptions ever escape from it and so is useful to call at module
// boundary.
//
// It must be only called when handling an active exception.
static void WXConsumeException();
#endif // wxUSE_EXCEPTIONS
#ifdef wxHAS_CALL_AFTER #ifdef wxHAS_CALL_AFTER
// Asynchronous method calls: these methods schedule the given method // Asynchronous method calls: these methods schedule the given method
// pointer for a later call (during the next idle event loop iteration). // pointer for a later call (during the next idle event loop iteration).

View File

@@ -1604,70 +1604,79 @@ bool wxEvtHandler::SafelyProcessEvent(wxEvent& event)
} }
catch ( ... ) catch ( ... )
{ {
wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); WXConsumeException();
return false;
}
#endif // wxUSE_EXCEPTIONS
}
#if wxUSE_EXCEPTIONS
/* static */
void wxEvtHandler::WXConsumeException()
{
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
try
{
if ( !wxTheApp || !wxTheApp->OnExceptionInMainLoop() )
{
if ( loop )
loop->Exit();
}
//else: continue running current event loop
}
catch ( ... )
{
// OnExceptionInMainLoop() threw, possibly rethrowing the same
// exception again. We have to deal with it here because we can't
// allow the exception to escape from the handling code, this will
// result in a crash at best (e.g. when using wxGTK as C++
// exceptions can't propagate through the C GTK+ code and corrupt
// the stack) and in something even more weird at worst (like
// exceptions completely disappearing into the void under some
// 64 bit versions of Windows).
if ( loop && !loop->IsYielding() )
loop->Exit();
// Give the application one last possibility to store the exception
// for rethrowing it later, when we get back to our code.
bool stored = false;
try try
{ {
if ( !wxTheApp || !wxTheApp->OnExceptionInMainLoop() ) if ( wxTheApp )
{ stored = wxTheApp->StoreCurrentException();
if ( loop )
loop->Exit();
}
//else: continue running current event loop
} }
catch ( ... ) catch ( ... )
{ {
// OnExceptionInMainLoop() threw, possibly rethrowing the same // StoreCurrentException() really shouldn't throw, but if it
// exception again. We have to deal with it here because we can't // did, take it as an indication that it didn't store it.
// allow the exception to escape from the handling code, this will }
// result in a crash at best (e.g. when using wxGTK as C++
// exceptions can't propagate through the C GTK+ code and corrupt
// the stack) and in something even more weird at worst (like
// exceptions completely disappearing into the void under some
// 64 bit versions of Windows).
if ( loop && !loop->IsYielding() )
loop->Exit();
// Give the application one last possibility to store the exception // If it didn't take it, just abort, at least like this we behave
// for rethrowing it later, when we get back to our code. // consistently everywhere.
bool stored = false; if ( !stored )
{
try try
{ {
if ( wxTheApp ) if ( wxTheApp )
stored = wxTheApp->StoreCurrentException(); wxTheApp->OnUnhandledException();
} }
catch ( ... ) catch ( ... )
{ {
// StoreCurrentException() really shouldn't throw, but if it // And OnUnhandledException() absolutely shouldn't throw,
// did, take it as an indication that it didn't store it. // but we still must account for the possibility that it
// did. At least show some information about the exception
// in this case.
wxTheApp->wxAppConsoleBase::OnUnhandledException();
} }
// If it didn't take it, just abort, at least like this we behave wxAbort();
// consistently everywhere.
if ( !stored )
{
try
{
if ( wxTheApp )
wxTheApp->OnUnhandledException();
}
catch ( ... )
{
// And OnUnhandledException() absolutely shouldn't throw,
// but we still must account for the possibility that it
// did. At least show some information about the exception
// in this case.
wxTheApp->wxAppConsoleBase::OnUnhandledException();
}
wxAbort();
}
} }
} }
return false;
#endif // wxUSE_EXCEPTIONS
} }
#endif // wxUSE_EXCEPTIONS
bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event) bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
{ {
const wxEventType eventType = event.GetEventType(); const wxEventType eventType = event.GetEventType();