From 41eecd7ce2e2200e5f76da1974a86c6f35831d1b Mon Sep 17 00:00:00 2001 From: gatecat Date: Tue, 20 Jul 2021 13:22:47 +0100 Subject: gui: Improve Fatal Error message Signed-off-by: gatecat --- CMakeLists.txt | 5 ++++ gui/application.cc | 68 +++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58b0fead..78c1caa1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,6 +168,11 @@ if (BUILD_GUI AND NOT BUILD_PYTHON) message(FATAL_ERROR "GUI requires Python to build") endif() +if (BUILD_GUI) + # For higher quality backtraces + set(CMAKE_ENABLE_EXPORTS ON) +endif() + find_package(PythonInterp 3.5 REQUIRED) if (BUILD_PYTHON) # TODO: sensible minimum Python version diff --git a/gui/application.cc b/gui/application.cc index 3f6d538b..d3260684 100644 --- a/gui/application.cc +++ b/gui/application.cc @@ -27,6 +27,10 @@ #include #include "log.h" +#ifdef __linux__ +#include +#endif + NEXTPNR_NAMESPACE_BEGIN #ifdef _WIN32 @@ -39,6 +43,53 @@ BOOL WINAPI WinHandler(DWORD dwCtrlType) } #endif +namespace { +#ifdef __linux__ +std::string get_backtrace_str() +{ + static const size_t MAX_BT_SIZE = 1024; + std::array bt_data; + int bt_len = backtrace(bt_data.data(), MAX_BT_SIZE); + char **bt_symbols = backtrace_symbols(bt_data.data(), bt_len); + if (bt_symbols == nullptr) + return ""; + std::ostringstream ss; + ss << "Backtrace: " << std::endl; + for (int i = 0; i < bt_len; i++) + ss << " " << bt_symbols[i] << std::endl; + free(bt_symbols); + return ss.str(); +} +#else +std::string get_backtrace_str() { return ""; } +#endif + +void do_error() +{ + std::string bt = get_backtrace_str(); + + std::exception_ptr eptr = std::current_exception(); + std::string err_msg = "Unknown Exception Type"; + + try { + if (eptr) { + std::rethrow_exception(eptr); + } + } catch (const std::exception &e) { + err_msg = e.what(); + } catch (...) { + } + + QString msg; + QTextStream out(&msg); + out << "Internal Error: " << err_msg.c_str() << "\n"; + out << bt.c_str(); + QMessageBox::critical(0, "Error", msg); + std::abort(); +} + +} // namespace + Application::Application(int &argc, char **argv, bool noantialiasing) : QApplication(argc, argv) { QSurfaceFormat fmt; @@ -64,23 +115,18 @@ Application::Application(int &argc, char **argv, bool noantialiasing) : QApplica #ifdef _WIN32 SetConsoleCtrlHandler((PHANDLER_ROUTINE)WinHandler, TRUE); #endif + + std::set_terminate(do_error); } bool Application::notify(QObject *receiver, QEvent *event) { - bool retVal = true; try { - retVal = QApplication::notify(receiver, event); - } catch (const assertion_failure &ex) { - QString msg; - QTextStream out(&msg); - out << ex.filename.c_str() << " at " << ex.line << "\n"; - out << ex.msg.c_str(); - QMessageBox::critical(0, "Error", msg); - } catch (...) { - QMessageBox::critical(0, "Error", "Fatal error !!!"); + return QApplication::notify(receiver, event); + } catch (log_execution_error_exception) { + QMessageBox::critical(0, "Error", "Pass failed, see log for details!"); + return true; } - return retVal; } NEXTPNR_NAMESPACE_END -- cgit v1.2.3