gui: Improve Fatal Error message

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2021-07-20 13:22:47 +01:00
parent f3be638ea9
commit 41eecd7ce2
2 changed files with 62 additions and 11 deletions

View File

@ -168,6 +168,11 @@ if (BUILD_GUI AND NOT BUILD_PYTHON)
message(FATAL_ERROR "GUI requires Python to build") message(FATAL_ERROR "GUI requires Python to build")
endif() endif()
if (BUILD_GUI)
# For higher quality backtraces
set(CMAKE_ENABLE_EXPORTS ON)
endif()
find_package(PythonInterp 3.5 REQUIRED) find_package(PythonInterp 3.5 REQUIRED)
if (BUILD_PYTHON) if (BUILD_PYTHON)
# TODO: sensible minimum Python version # TODO: sensible minimum Python version

View File

@ -27,6 +27,10 @@
#include <exception> #include <exception>
#include "log.h" #include "log.h"
#ifdef __linux__
#include <execinfo.h>
#endif
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
#ifdef _WIN32 #ifdef _WIN32
@ -39,6 +43,53 @@ BOOL WINAPI WinHandler(DWORD dwCtrlType)
} }
#endif #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) Application::Application(int &argc, char **argv, bool noantialiasing) : QApplication(argc, argv)
{ {
QSurfaceFormat fmt; QSurfaceFormat fmt;
@ -64,23 +115,18 @@ Application::Application(int &argc, char **argv, bool noantialiasing) : QApplica
#ifdef _WIN32 #ifdef _WIN32
SetConsoleCtrlHandler((PHANDLER_ROUTINE)WinHandler, TRUE); SetConsoleCtrlHandler((PHANDLER_ROUTINE)WinHandler, TRUE);
#endif #endif
std::set_terminate(do_error);
} }
bool Application::notify(QObject *receiver, QEvent *event) bool Application::notify(QObject *receiver, QEvent *event)
{ {
bool retVal = true;
try { try {
retVal = QApplication::notify(receiver, event); return QApplication::notify(receiver, event);
} catch (const assertion_failure &ex) { } catch (log_execution_error_exception) {
QString msg; QMessageBox::critical(0, "Error", "Pass failed, see log for details!");
QTextStream out(&msg); return true;
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 retVal;
} }
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END