mirror of
https://github.com/stenzek/duckstation.git
synced 2026-02-09 16:04:33 +00:00
Common: Use NSAlert for assertion failures/panics
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__ANDROID__)
|
||||
|
||||
#include "assert.h"
|
||||
#include "crash_handler.h"
|
||||
|
||||
@@ -71,27 +73,6 @@ static void ResumeThreads(HANDLE hSnapshot)
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// Define as a weak symbol for ancient devices that don't have it.
|
||||
extern "C" __attribute__((weak)) void android_set_abort_message(const char*);
|
||||
#endif
|
||||
|
||||
[[noreturn]] ALWAYS_INLINE static void AbortWithMessage(const char* szMsg)
|
||||
{
|
||||
#ifndef __ANDROID__
|
||||
std::fputs(szMsg, stderr);
|
||||
std::fflush(stderr);
|
||||
std::abort();
|
||||
#else
|
||||
if (&android_set_abort_message)
|
||||
android_set_abort_message(szMsg);
|
||||
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char* szFile, unsigned uLine)
|
||||
@@ -125,7 +106,9 @@ void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char*
|
||||
|
||||
ResumeThreads(pHandle);
|
||||
#else
|
||||
AbortWithMessage(szMsg);
|
||||
std::fputs(szMsg, stderr);
|
||||
std::fflush(stderr);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -157,6 +140,10 @@ void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char*
|
||||
|
||||
ResumeThreads(pHandle);
|
||||
#else
|
||||
AbortWithMessage(szMsg);
|
||||
std::fputs(szMsg, stderr);
|
||||
std::fflush(stderr);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // !defined(__APPLE__) && !defined(__ANDROID__)
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <cinttypes>
|
||||
#include <dlfcn.h>
|
||||
#include <mach/mach_time.h>
|
||||
@@ -142,3 +144,73 @@ bool CocoaTools::DelayedLaunch(std::string_view file, std::span<const std::strin
|
||||
return [task launchAndReturnError:nil];
|
||||
}
|
||||
}
|
||||
|
||||
void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char* szFile, unsigned uLine)
|
||||
{
|
||||
if (![NSThread isMainThread])
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(),
|
||||
[szMessage, szFunction, szFile, uLine]() { Y_OnAssertFailed(szMessage, szFunction, szFile, uLine); });
|
||||
return;
|
||||
}
|
||||
|
||||
char szMsg[512];
|
||||
std::snprintf(szMsg, sizeof(szMsg), "%s in function %s (%s:%u)\n", szMessage, szFunction, szFile, uLine);
|
||||
std::fputs(szMsg, stderr);
|
||||
std::fflush(stderr);
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
NSAlert* alert = [[[NSAlert alloc] init] autorelease];
|
||||
[alert setMessageText:@"Assertion Failed"];
|
||||
|
||||
NSString* text = [NSString stringWithFormat:@"%s in function %s (%s:%u)\nPress Abort to exit, Break to break to "
|
||||
@"debugger, or Ignore to attempt to continue.",
|
||||
szMessage, szFunction, szFile, uLine];
|
||||
[alert setInformativeText:text];
|
||||
[alert setAlertStyle:NSAlertStyleCritical];
|
||||
[alert addButtonWithTitle:@"Abort"];
|
||||
[alert addButtonWithTitle:@"Break"];
|
||||
[alert addButtonWithTitle:@"Ignore"];
|
||||
|
||||
const NSModalResponse response = [alert runModal];
|
||||
if (response == NSAlertFirstButtonReturn)
|
||||
std::abort();
|
||||
else if (response == NSAlertSecondButtonReturn)
|
||||
__builtin_debugtrap();
|
||||
}
|
||||
}
|
||||
|
||||
[[noreturn]] void Y_OnPanicReached(const char* szMessage, const char* szFunction, const char* szFile, unsigned uLine)
|
||||
{
|
||||
if (![NSThread isMainThread])
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(),
|
||||
[szMessage, szFunction, szFile, uLine]() { Y_OnAssertFailed(szMessage, szFunction, szFile, uLine); });
|
||||
}
|
||||
else
|
||||
{
|
||||
char szMsg[512];
|
||||
std::snprintf(szMsg, sizeof(szMsg), "%s in function %s (%s:%u)\n", szMessage, szFunction, szFile, uLine);
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
NSAlert* alert = [[[NSAlert alloc] init] autorelease];
|
||||
[alert setMessageText:@"Critical Error"];
|
||||
|
||||
NSString* text =
|
||||
[NSString stringWithFormat:@"%s in function %s (%s:%u)\nDo you want to attempt to break into a debugger?",
|
||||
szMessage, szFunction, szFile, uLine];
|
||||
[alert setInformativeText:text];
|
||||
[alert setAlertStyle:NSAlertStyleCritical];
|
||||
[alert addButtonWithTitle:@"Abort"];
|
||||
[alert addButtonWithTitle:@"Break"];
|
||||
|
||||
const NSModalResponse response = [alert runModal];
|
||||
if (response == NSAlertSecondButtonReturn)
|
||||
__builtin_debugtrap();
|
||||
}
|
||||
}
|
||||
|
||||
std::abort();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user