From 239469457d632fcb7ba8d37b8811c7499b26d5f7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 15 Nov 2016 00:55:08 +0100 Subject: [PATCH] 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. --- include/wx/event.h | 12 +++++ src/common/event.cpp | 101 +++++++++++++++++++++++-------------------- 2 files changed, 67 insertions(+), 46 deletions(-) diff --git a/include/wx/event.h b/include/wx/event.h index 44d378ac01..89d4659e15 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -3386,6 +3386,18 @@ public: // NOTE: uses AddPendingEvent(); call only from secondary threads #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 // Asynchronous method calls: these methods schedule the given method // pointer for a later call (during the next idle event loop iteration). diff --git a/src/common/event.cpp b/src/common/event.cpp index 2faf29971c..f1bb67798a 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -1604,70 +1604,79 @@ bool wxEvtHandler::SafelyProcessEvent(wxEvent& event) } 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 { - if ( !wxTheApp || !wxTheApp->OnExceptionInMainLoop() ) - { - if ( loop ) - loop->Exit(); - } - //else: continue running current event loop + if ( wxTheApp ) + stored = wxTheApp->StoreCurrentException(); } 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(); + // StoreCurrentException() really shouldn't throw, but if it + // did, take it as an indication that it didn't store it. + } - // Give the application one last possibility to store the exception - // for rethrowing it later, when we get back to our code. - bool stored = false; + // If it didn't take it, just abort, at least like this we behave + // consistently everywhere. + if ( !stored ) + { try { if ( wxTheApp ) - stored = wxTheApp->StoreCurrentException(); + wxTheApp->OnUnhandledException(); } catch ( ... ) { - // StoreCurrentException() really shouldn't throw, but if it - // did, take it as an indication that it didn't store it. + // 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(); } - // If it didn't take it, just abort, at least like this we behave - // 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(); - } + wxAbort(); } } - - return false; -#endif // wxUSE_EXCEPTIONS } +#endif // wxUSE_EXCEPTIONS + bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event) { const wxEventType eventType = event.GetEventType();