macOS: put assertion message into crash reporter dialog.

This commit makes FatalError a GUI-dependent function.
This commit is contained in:
whitequark 2018-07-17 12:32:58 +00:00
parent eb5501ecd6
commit a93283df9d
9 changed files with 105 additions and 65 deletions

View File

@ -13,6 +13,11 @@ static System SYS;
static int IsInit = 0;
void SolveSpace::Platform::FatalError(std::string message) {
fprintf(stderr, "%s", message.c_str());
abort();
}
void Group::GenerateEquations(IdList<Equation,hEquation> *) {
// Nothing to do for now.
}

View File

@ -76,6 +76,12 @@ std::string AcceleratorDescription(const KeyboardEvent &accel);
// Interfaces
//-----------------------------------------------------------------------------
// Handling fatal errors.
#if defined(__GNUC__)
__attribute__((noreturn))
#endif
void FatalError(std::string message);
// A native settings store.
class Settings {
public:

View File

@ -25,6 +25,15 @@
namespace SolveSpace {
namespace Platform {
//-----------------------------------------------------------------------------
// Fatal errors
//-----------------------------------------------------------------------------
void FatalError(std::string message) {
fprintf(stderr, "%s", message.c_str());
abort();
}
//-----------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------

View File

@ -52,6 +52,33 @@ static NSString* Wrap(const std::string &s) {
namespace SolveSpace {
namespace Platform {
//-----------------------------------------------------------------------------
// Fatal errors
//-----------------------------------------------------------------------------
// This gets put into the "Application Specific Information" field in crash
// reporter dialog.
typedef struct {
unsigned version __attribute__((aligned(8)));
const char *message __attribute__((aligned(8)));
const char *signature __attribute__((aligned(8)));
const char *backtrace __attribute__((aligned(8)));
const char *message2 __attribute__((aligned(8)));
void *reserved __attribute__((aligned(8)));
void *reserved2 __attribute__((aligned(8)));
} crash_info_t;
#define CRASH_VERSION 4
crash_info_t crashAnnotation __attribute__((section("__DATA,__crash_info"))) = {
CRASH_VERSION, NULL, NULL, NULL, NULL, NULL, NULL
};
void FatalError(std::string message) {
crashAnnotation.message = message.c_str();
abort();
}
//-----------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------

View File

@ -18,6 +18,35 @@ std::shared_ptr<ViewportCanvas> CreateRenderer() {
namespace Platform {
//-----------------------------------------------------------------------------
// Fatal errors
//-----------------------------------------------------------------------------
void FatalError(std::string message) {
fprintf(stderr, "%s", message.c_str());
#if !defined(LIBRARY) && defined(HAVE_BACKTRACE)
static void *ptrs[1024] = {};
size_t nptrs = backtrace(ptrs, sizeof(ptrs) / sizeof(ptrs[0]));
char **syms = backtrace_symbols(ptrs, nptrs);
fprintf(stderr, "Backtrace:\n");
if(syms != NULL) {
for(size_t i = 0; i < nptrs; i++) {
fprintf(stderr, "%2zu: %s\n", i, syms[i]);
}
} else {
for(size_t i = 0; i < nptrs; i++) {
fprintf(stderr, "%2zu: %p\n", i, ptrs[i]);
}
}
#else
fprintf(stderr, "Backtrace support not compiled in.\n");
#endif
abort();
}
//-----------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------

View File

@ -9,6 +9,7 @@
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <shellapi.h>
#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0
@ -102,6 +103,34 @@ static int Clamp(int x, int a, int b) {
return max(a, min(x, b));
}
//-----------------------------------------------------------------------------
// Fatal errors
//-----------------------------------------------------------------------------
bool handlingFatalError = false;
void FatalError(std::string message) {
// Indicate that we're handling a fatal error, to avoid re-entering application code
// and potentially crashing even harder.
handlingFatalError = true;
message += "\nGenerate debug report?";
switch(MessageBoxW(NULL, Platform::Widen(message).c_str(),
L"Fatal error — SolveSpace",
MB_ICONERROR|MB_TASKMODAL|MB_SETFOREGROUND|MB_TOPMOST|
MB_OKCANCEL|MB_DEFBUTTON2)) {
case IDOK:
abort();
case IDCANCEL:
default: {
WCHAR appPath[MAX_PATH] = {};
GetModuleFileNameW(NULL, appPath, sizeof(appPath));
ShellExecuteW(NULL, L"open", appPath, NULL, NULL, SW_SHOW);
_exit(1);
}
}
}
//-----------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------

View File

@ -9,13 +9,6 @@
namespace Platform {
// Handling fatal errors.
#if defined(__GNUC__)
__attribute__((noreturn))
#endif
void FatalError(std::string message);
extern bool handlingFatalError;
// UTF-8 ⟷ UTF-16 conversion, for Windows.
#if defined(WIN32)
std::string Narrow(const wchar_t *s);

View File

@ -27,35 +27,6 @@ void dbp(const char *str, ...)
fputc('\n', stderr);
}
namespace Platform {
void FatalError(std::string message) {
fprintf(stderr, "%s", message.c_str());
#if !defined(LIBRARY) && defined(HAVE_BACKTRACE)
static void *ptrs[1024] = {};
size_t nptrs = backtrace(ptrs, sizeof(ptrs) / sizeof(ptrs[0]));
char **syms = backtrace_symbols(ptrs, nptrs);
fprintf(stderr, "Backtrace:\n");
if(syms != NULL) {
for(size_t i = 0; i < nptrs; i++) {
fprintf(stderr, "%2zu: %s\n", i, syms[i]);
}
} else {
for(size_t i = 0; i < nptrs; i++) {
fprintf(stderr, "%2zu: %p\n", i, ptrs[i]);
}
}
#else
fprintf(stderr, "Backtrace support not compiled in.\n");
#endif
abort();
}
}
//-----------------------------------------------------------------------------
// A separate heap, on which we allocate expressions. Maybe a bit faster,
// since fragmentation is less of a concern, and it also makes it possible

View File

@ -35,35 +35,6 @@ void dbp(const char *str, ...)
#endif
}
namespace Platform {
bool handlingFatalError = false;
void FatalError(std::string message) {
// Indicate that we're handling a fatal error, to avoid re-entering application code
// and potentially crashing even harder.
handlingFatalError = true;
message += "\nGenerate debug report?";
switch(MessageBoxW(NULL, Platform::Widen(message).c_str(),
L"Fatal error — SolveSpace",
MB_ICONERROR|MB_TASKMODAL|MB_SETFOREGROUND|MB_TOPMOST|
MB_OKCANCEL|MB_DEFBUTTON2)) {
case IDOK:
abort();
case IDCANCEL:
default: {
WCHAR appPath[MAX_PATH] = {};
GetModuleFileNameW(NULL, appPath, sizeof(appPath));
ShellExecuteW(NULL, L"open", appPath, NULL, NULL, SW_SHOW);
_exit(1);
}
}
}
}
//-----------------------------------------------------------------------------
// A separate heap, on which we allocate expressions. Maybe a bit faster,
// since no fragmentation issues whatsoever, and it also makes it possible