GUI_App: Refactor exception handling

This commit is contained in:
Vojtech Kral 2019-04-09 11:28:11 +02:00
parent 2494dc6706
commit 64ce604ff4
2 changed files with 51 additions and 27 deletions

View file

@ -19,6 +19,8 @@
#include <wx/wupdlock.h> #include <wx/wupdlock.h>
#include <wx/filefn.h> #include <wx/filefn.h>
#include <wx/sysopt.h> #include <wx/sysopt.h>
#include <wx/msgdlg.h>
#include <wx/log.h>
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
@ -94,6 +96,34 @@ static void register_dpi_event()
#endif #endif
} }
static void generic_exception_handle()
{
// Note: Some wxWidgets APIs use wxLogError() to report errors, eg. wxImage
// - see https://docs.wxwidgets.org/3.1/classwx_image.html#aa249e657259fe6518d68a5208b9043d0
//
// wxLogError typically goes around exception handling and display an error dialog some time
// after an error is logged even if exception handling and OnExceptionInMainLoop() take place.
// This is why we use wxLogError() here as well instead of a custom dialog, because it accumulates
// errors if multiple have been collected and displays just one error message for all of them.
// Otherwise we would get multiple error messages for one missing png, for example.
//
// If a custom error message window (or some other solution) were to be used, it would be necessary
// to turn off wxLogError() usage in wx APIs, most notably in wxImage
// - see https://docs.wxwidgets.org/trunk/classwx_image.html#aa32e5d3507cc0f8c3330135bc0befc6a
try {
throw;
} catch (const std::exception &ex) {
wxLogError("Internal error: %s", ex.what());
BOOST_LOG_TRIVIAL(error) << boost::format("Uncaught exception: %1%") % ex.what();
throw;
} catch (...) {
wxLogError("Unknown internal error");
BOOST_LOG_TRIVIAL(error) << "Uncaught exception: Unknown error";
}
}
IMPLEMENT_APP(GUI_App) IMPLEMENT_APP(GUI_App)
GUI_App::GUI_App() GUI_App::GUI_App()
@ -103,6 +133,16 @@ GUI_App::GUI_App()
{} {}
bool GUI_App::OnInit() bool GUI_App::OnInit()
{
try {
return on_init_inner();
} catch (...) {
generic_exception_handle();
return false;
}
}
bool GUI_App::on_init_inner()
{ {
// Verify resources path // Verify resources path
const wxString resources_dir = from_u8(Slic3r::resources_dir()); const wxString resources_dir = from_u8(Slic3r::resources_dir());
@ -132,13 +172,7 @@ bool GUI_App::OnInit()
// just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory
// supplied as argument to --datadir; in that case we should still run the wizard // supplied as argument to --datadir; in that case we should still run the wizard
try { preset_bundle->setup_directories();
preset_bundle->setup_directories();
} catch (const std::exception &ex) {
show_error(nullptr, ex.what());
// Exit the application.
return false;
}
app_conf_exists = app_config->exists(); app_conf_exists = app_config->exists();
// load settings // load settings
@ -161,11 +195,11 @@ bool GUI_App::OnInit()
// Suppress the '- default -' presets. // Suppress the '- default -' presets.
preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1"); preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1");
try { try {
preset_bundle->load_presets(*app_config); preset_bundle->load_presets(*app_config);
} catch (const std::exception &ex) { } catch (const std::exception &ex) {
show_error(nullptr, ex.what()); show_error(nullptr, from_u8(ex.what()));
} }
register_dpi_event(); register_dpi_event();
@ -184,8 +218,8 @@ bool GUI_App::OnInit()
Bind(wxEVT_IDLE, [this](wxIdleEvent& event) Bind(wxEVT_IDLE, [this](wxIdleEvent& event)
{ {
if (! plater_) if (! plater_)
return; return;
if (app_config->dirty() && app_config->get("autosave") == "1") if (app_config->dirty() && app_config->get("autosave") == "1")
app_config->save(); app_config->save();
@ -207,7 +241,7 @@ bool GUI_App::OnInit()
mainframe->Close(); mainframe->Close();
} }
} catch (const std::exception &ex) { } catch (const std::exception &ex) {
show_error(nullptr, ex.what()); show_error(nullptr, from_u8(ex.what()));
} }
CallAfter([this] { CallAfter([this] {
@ -752,18 +786,7 @@ void GUI_App::load_current_presets()
bool GUI_App::OnExceptionInMainLoop() bool GUI_App::OnExceptionInMainLoop()
{ {
try { generic_exception_handle();
throw;
} catch (const std::exception &ex) {
const std::string error = (boost::format("Uncaught exception: %1%") % ex.what()).str();
BOOST_LOG_TRIVIAL(error) << error;
show_error(nullptr, from_u8(error));
} catch (...) {
const char *error = "Uncaught exception: Unknown error";
BOOST_LOG_TRIVIAL(error) << error;
show_error(nullptr, from_u8(error));
}
return false; return false;
} }

View file

@ -169,6 +169,7 @@ public:
PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); } PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); }
private: private:
bool on_init_inner();
void window_pos_save(wxTopLevelWindow* window, const std::string &name); void window_pos_save(wxTopLevelWindow* window, const std::string &name);
void window_pos_restore(wxTopLevelWindow* window, const std::string &name); void window_pos_restore(wxTopLevelWindow* window, const std::string &name);
void window_pos_sanitize(wxTopLevelWindow* window); void window_pos_sanitize(wxTopLevelWindow* window);