Add exception and crashes catching with processing on iOS/macOS
This commit is contained in:
@@ -274,6 +274,24 @@ void Engine::RequestExit(int32 exitCode, FatalErrorType error)
|
||||
RequestingExit();
|
||||
}
|
||||
|
||||
#if !BUILD_SHIPPING
|
||||
|
||||
void Engine::Crash(FatalErrorType error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case FatalErrorType::None:
|
||||
case FatalErrorType::Exception:
|
||||
*((int32*)3) = 11;
|
||||
break;
|
||||
default:
|
||||
Platform::Fatal(TEXT("Crash Test"), nullptr, error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Engine::OnFixedUpdate()
|
||||
{
|
||||
PROFILE_CPU_NAMED("Fixed Update");
|
||||
|
||||
@@ -125,6 +125,14 @@ public:
|
||||
/// <param name="error">The fatal error type (or None on graceful exit).</param>
|
||||
API_FUNCTION() static void RequestExit(int32 exitCode = 0, FatalErrorType error = FatalErrorType::None);
|
||||
|
||||
#if !BUILD_SHIPPING
|
||||
/// <summary>
|
||||
/// Crashes the engine. Utility used to test crash reporting or game stability monitoring systems.
|
||||
/// </summary>
|
||||
/// <param name="error">The fatal error type.</param>
|
||||
API_FUNCTION(Attributes="DebugCommand") static void Crash(FatalErrorType error = FatalErrorType::Exception);
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Fixed update callback used by the physics simulation (fixed stepping).
|
||||
|
||||
@@ -58,6 +58,43 @@ int32 AutoreleasePoolInterval = 0;
|
||||
|
||||
float ApplePlatform::ScreenScale = 1.0f;
|
||||
|
||||
static void CrashHandler(int32 signal, siginfo_t* info, void* context)
|
||||
{
|
||||
// Skip if engine already crashed
|
||||
if (Engine::FatalError != FatalErrorType::None)
|
||||
return;
|
||||
|
||||
// Get exception info
|
||||
String errorMsg(TEXT("Unhandled exception: "));
|
||||
switch (signal)
|
||||
{
|
||||
#define CASE(x) case x: errorMsg += TEXT(#x); break
|
||||
CASE(SIGABRT);
|
||||
CASE(SIGILL);
|
||||
CASE(SIGSEGV);
|
||||
CASE(SIGQUIT);
|
||||
CASE(SIGEMT);
|
||||
CASE(SIGFPE);
|
||||
CASE(SIGBUS);
|
||||
CASE(SIGSYS);
|
||||
#undef CASE
|
||||
default:
|
||||
errorMsg += StringUtils::ToString(signal);
|
||||
}
|
||||
|
||||
// Log exception and return to the crash location when using debugger
|
||||
if (Platform::IsDebuggerPresent())
|
||||
{
|
||||
LOG_STR(Error, errorMsg);
|
||||
const String stackTrace = Platform::GetStackTrace(3, 60, nullptr);
|
||||
LOG_STR(Error, stackTrace);
|
||||
return;
|
||||
}
|
||||
|
||||
// Crash engine
|
||||
Platform::Fatal(errorMsg.Get(), nullptr, FatalErrorType::Exception);
|
||||
}
|
||||
|
||||
String AppleUtils::ToString(CFStringRef str)
|
||||
{
|
||||
if (!str)
|
||||
@@ -90,41 +127,50 @@ NSString* AppleUtils::ToNSString(const char* string)
|
||||
return ret ? ret : @"";
|
||||
}
|
||||
|
||||
|
||||
NSArray* AppleUtils::ParseArguments(NSString* argsString) {
|
||||
NSMutableArray *argsArray = [NSMutableArray array];
|
||||
NSMutableString *currentArg = [NSMutableString string];
|
||||
NSArray* AppleUtils::ParseArguments(NSString* argsString)
|
||||
{
|
||||
NSMutableArray* argsArray = [NSMutableArray array];
|
||||
NSMutableString* currentArg = [NSMutableString string];
|
||||
BOOL insideQuotes = NO;
|
||||
|
||||
for (NSInteger i = 0; i < argsString.length; ++i) {
|
||||
|
||||
for (NSInteger i = 0; i < argsString.length; i++)
|
||||
{
|
||||
unichar c = [argsString characterAtIndex:i];
|
||||
|
||||
if (c == '\"') {
|
||||
if (insideQuotes) {
|
||||
if (c == '\"')
|
||||
{
|
||||
if (insideQuotes)
|
||||
{
|
||||
[argsArray addObject:[currentArg copy]];
|
||||
[currentArg setString:@""];
|
||||
insideQuotes = NO;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
insideQuotes = YES;
|
||||
}
|
||||
} else if (c == ' ' && !insideQuotes) {
|
||||
if (currentArg.length > 0) {
|
||||
}
|
||||
else if (c == ' ' && !insideQuotes)
|
||||
{
|
||||
if (currentArg.length > 0)
|
||||
{
|
||||
[argsArray addObject:[currentArg copy]];
|
||||
[currentArg setString:@""];
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
[currentArg appendFormat:@"%C", c];
|
||||
}
|
||||
}
|
||||
|
||||
if (currentArg.length > 0) {
|
||||
if (currentArg.length > 0)
|
||||
{
|
||||
[argsArray addObject:[currentArg copy]];
|
||||
}
|
||||
|
||||
|
||||
return [argsArray copy];
|
||||
}
|
||||
|
||||
|
||||
typedef uint16_t offset_t;
|
||||
#define align_mem_up(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
@@ -376,6 +422,21 @@ bool ApplePlatform::Init()
|
||||
setrlimit(RLIMIT_NOFILE, &limit);
|
||||
}
|
||||
|
||||
// Register crash handler
|
||||
struct sigaction action;
|
||||
Platform::MemoryClear(&action, sizeof(action));
|
||||
action.sa_sigaction = CrashHandler;
|
||||
sigemptyset(&action.sa_mask);
|
||||
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
sigaction(SIGABRT, &action, nullptr);
|
||||
sigaction(SIGILL, &action, nullptr);
|
||||
sigaction(SIGSEGV, &action, nullptr);
|
||||
sigaction(SIGQUIT, &action, nullptr);
|
||||
sigaction(SIGEMT, &action, nullptr);
|
||||
sigaction(SIGFPE, &action, nullptr);
|
||||
sigaction(SIGBUS, &action, nullptr);
|
||||
sigaction(SIGSYS, &action, nullptr);
|
||||
|
||||
AutoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user