diff options
author | gatecat <gatecat@ds0.me> | 2021-07-20 13:22:47 +0100 |
---|---|---|
committer | gatecat <gatecat@ds0.me> | 2021-07-20 15:01:34 +0100 |
commit | 41eecd7ce2e2200e5f76da1974a86c6f35831d1b (patch) | |
tree | 24240ecb3313c17c931b9ffdfd70e80411e4b2e2 | |
parent | f3be638ea9536511d329d3e1ad726e847916f122 (diff) | |
download | nextpnr-41eecd7ce2e2200e5f76da1974a86c6f35831d1b.tar.gz nextpnr-41eecd7ce2e2200e5f76da1974a86c6f35831d1b.tar.bz2 nextpnr-41eecd7ce2e2200e5f76da1974a86c6f35831d1b.zip |
gui: Improve Fatal Error message
Signed-off-by: gatecat <gatecat@ds0.me>
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | 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 <exception> #include "log.h" +#ifdef __linux__ +#include <execinfo.h> +#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<void *, MAX_BT_SIZE> 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 |