recover from exception on iOS and macOS using signals and log the stacktrace
This commit is contained in:
@@ -19,32 +19,6 @@
|
||||
std::deque<std::packaged_task<void()>> tasklist;
|
||||
std::mutex task_mutex;
|
||||
|
||||
void global_exception_handler(NSException* e)
|
||||
{
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Recovery"
|
||||
defaultButton:@"OK" alternateButton:@"Cancel"
|
||||
otherButton:nil informativeTextWithFormat:@"Exception"];
|
||||
[alert runModal];
|
||||
|
||||
if (App::I.canvas && App::I.canvas->m_canvas)
|
||||
App::I.canvas->m_canvas->project_save_thread(App::I.data_path + "/recovery.ppi");
|
||||
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
void global_signal_handler(int e)
|
||||
{
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Recovery"
|
||||
defaultButton:@"OK" alternateButton:@"Cancel"
|
||||
otherButton:nil informativeTextWithFormat:@"Signal"];
|
||||
[alert runModal];
|
||||
|
||||
if (App::I.canvas && App::I.canvas->m_canvas)
|
||||
App::I.canvas->m_canvas->project_save_thread(App::I.data_path + "/recovery.ppi");
|
||||
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
@implementation View
|
||||
- (void)async_lock
|
||||
{
|
||||
@@ -451,6 +425,8 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
|
||||
}
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"NSApplicationCrashOnExceptions": @YES }];
|
||||
|
||||
if (!App::I.check_license())
|
||||
return;
|
||||
|
||||
@@ -492,9 +468,8 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
install_global_handlers();
|
||||
AppOSX* app = [AppOSX sharedApplication];
|
||||
NSSetUncaughtExceptionHandler(&global_exception_handler);
|
||||
signal(SIGFPE, global_signal_handler);
|
||||
[app run];
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
ADC6F4681F3E66FB004177FA /* app_dialogs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADC6F4651F3E66FA004177FA /* app_dialogs.cpp */; };
|
||||
ADD6AFD71F94DEB000E92461 /* node_progress_bar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADD6AFD61F94DEAF00E92461 /* node_progress_bar.cpp */; };
|
||||
ADD6AFD81F94DEB000E92461 /* node_progress_bar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADD6AFD61F94DEAF00E92461 /* node_progress_bar.cpp */; };
|
||||
ADD7D26F1EBF9AE300D5A897 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = ADD7D26E1EBF9AE300D5A897 /* main.m */; };
|
||||
ADD7D26F1EBF9AE300D5A897 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADD7D26E1EBF9AE300D5A897 /* main.cpp */; };
|
||||
ADD7D2721EBF9AE300D5A897 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = ADD7D2711EBF9AE300D5A897 /* AppDelegate.m */; };
|
||||
ADD7D2791EBF9AE300D5A897 /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ADD7D2781EBF9AE300D5A897 /* GameViewController.m */; };
|
||||
ADD7D27C1EBF9AE300D5A897 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = ADD7D27A1EBF9AE300D5A897 /* Main.storyboard */; };
|
||||
@@ -397,7 +397,7 @@
|
||||
ADD6AFD51F94DEAF00E92461 /* node_progress_bar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = node_progress_bar.h; sourceTree = "<group>"; };
|
||||
ADD6AFD61F94DEAF00E92461 /* node_progress_bar.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = node_progress_bar.cpp; sourceTree = "<group>"; };
|
||||
ADD7D26B1EBF9AE300D5A897 /* PanoPainter.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PanoPainter.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
ADD7D26E1EBF9AE300D5A897 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
ADD7D26E1EBF9AE300D5A897 /* main.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = main.cpp; sourceTree = "<group>"; };
|
||||
ADD7D2701EBF9AE300D5A897 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
ADD7D2711EBF9AE300D5A897 /* AppDelegate.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
ADD7D2771EBF9AE300D5A897 /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = "<group>"; };
|
||||
@@ -781,7 +781,7 @@
|
||||
children = (
|
||||
ADEBA9082069A50E0085AE16 /* objc_utils.cpp */,
|
||||
ADEBA9072069A50E0085AE16 /* objc_utils.h */,
|
||||
ADD7D26E1EBF9AE300D5A897 /* main.m */,
|
||||
ADD7D26E1EBF9AE300D5A897 /* main.cpp */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
@@ -1250,7 +1250,7 @@
|
||||
ADD7D2A21EBF9E1C00D5A897 /* util.cpp in Sources */,
|
||||
ADD7D2791EBF9AE300D5A897 /* GameViewController.m in Sources */,
|
||||
AD4CEF142156B2C60097F4BD /* node_about.cpp in Sources */,
|
||||
ADD7D26F1EBF9AE300D5A897 /* main.m in Sources */,
|
||||
ADD7D26F1EBF9AE300D5A897 /* main.cpp in Sources */,
|
||||
ADC0EB431FC36E88004079BB /* node_dialog_picker.cpp in Sources */,
|
||||
ADD7D2A01EBF9E1C00D5A897 /* image.cpp in Sources */,
|
||||
ADD7D2A11EBF9E1C00D5A897 /* texture.cpp in Sources */,
|
||||
@@ -1333,7 +1333,6 @@
|
||||
DEVELOPMENT_TEAM = ERD9AYQ49S;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/libs/ZipArchive/Mac",
|
||||
);
|
||||
INFOPLIST_FILE = "PanoPainter-OSX/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
@@ -1357,7 +1356,6 @@
|
||||
DEVELOPMENT_TEAM = ERD9AYQ49S;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/libs/ZipArchive/Mac",
|
||||
);
|
||||
INFOPLIST_FILE = "PanoPainter-OSX/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
@@ -1672,7 +1670,6 @@
|
||||
DEVELOPMENT_TEAM = ERD9AYQ49S;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/libs/ZipArchive/iOS",
|
||||
);
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"/Users/omimac/Downloads/curl-android-ios-master/prebuilt-with-ssl/iOS/include",
|
||||
@@ -1710,7 +1707,6 @@
|
||||
DEVELOPMENT_TEAM = ERD9AYQ49S;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/libs/ZipArchive/iOS",
|
||||
);
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"/Users/omimac/Downloads/curl-android-ios-master/prebuilt-with-ssl/iOS/include",
|
||||
|
||||
@@ -11,22 +11,6 @@
|
||||
#include "app.h"
|
||||
#include <WTSonarPenDriver.h>
|
||||
|
||||
void global_exception_handler(NSException* e)
|
||||
{
|
||||
if (App::I.canvas && App::I.canvas->m_canvas)
|
||||
App::I.canvas->m_canvas->project_save_thread(App::I.data_path + "/recovery.ppi");
|
||||
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
void global_signal_handler(int e)
|
||||
{
|
||||
if (App::I.canvas && App::I.canvas->m_canvas)
|
||||
App::I.canvas->m_canvas->project_save_thread(App::I.data_path + "/recovery.ppi");
|
||||
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
@interface AppDelegate () {
|
||||
GameViewController* view;
|
||||
WTSonarPenDriver* sonarpen_driver;
|
||||
@@ -68,8 +52,6 @@ void global_signal_handler(int e)
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
NSSetUncaughtExceptionHandler(&global_exception_handler);
|
||||
// sonarpen_driver = [[WTSonarPenDriver alloc] initWithApplication:application];
|
||||
// [sonarpen_driver start];
|
||||
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(penStatusChanged) name:WTSonarPenDriverStateChangedNotification object:nil];
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
#include "objc_utils.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
install_global_handlers();
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
#include "pch.h"
|
||||
#include "objc_utils.h"
|
||||
#include "log.h"
|
||||
#include "app.h"
|
||||
#include <atomic>
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
|
||||
@implementation PathWithModDate
|
||||
@end
|
||||
|
||||
@implementation ObjcUtils
|
||||
+ (NSArray*)getFilesAtPathSortedByModificationDate:(NSString*)folderPath
|
||||
{
|
||||
@@ -34,3 +34,42 @@
|
||||
}
|
||||
@end
|
||||
#endif
|
||||
|
||||
|
||||
std::string base_address;
|
||||
std::atomic_flag handler_executed;
|
||||
void exception_handler(NSException *exception)
|
||||
{
|
||||
if (handler_executed.test_and_set())
|
||||
exit(0);
|
||||
LOG("exception %s\n", [[exception name] cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
NSString* callstack = [[NSThread callStackSymbols] componentsJoinedByString:@"\n"];
|
||||
LOG("base:\n%s\ncallstack:\n%s", base_address.c_str(), [callstack cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
if (App::I.canvas && App::I.canvas->m_canvas)
|
||||
App::I.canvas->m_canvas->project_save_thread(App::I.data_path + "/recovery.ppi");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void signal_handler (int signo) {
|
||||
if (handler_executed.test_and_set())
|
||||
exit(0);
|
||||
LOG("signal %d\n", signo);
|
||||
NSString* callstack = [[NSThread callStackSymbols] componentsJoinedByString:@"\n"];
|
||||
LOG("base:\n%s\ncallstack:\n%s", base_address.c_str(), [callstack cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
if (App::I.canvas && App::I.canvas->m_canvas)
|
||||
App::I.canvas->m_canvas->project_save_thread(App::I.data_path + "/recovery.ppi");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void install_global_handlers()
|
||||
{
|
||||
NSString* callstack = [[NSThread callStackSymbols] componentsJoinedByString:@"\n"];
|
||||
base_address = [callstack cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
NSSetUncaughtExceptionHandler(exception_handler);
|
||||
signal(SIGABRT, signal_handler);
|
||||
signal(SIGILL, signal_handler);
|
||||
signal(SIGSEGV, signal_handler);
|
||||
signal(SIGFPE, signal_handler);
|
||||
signal(SIGBUS, signal_handler);
|
||||
signal(SIGPIPE, signal_handler);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
|
||||
@interface PathWithModDate : NSObject
|
||||
@property (strong) NSString *path;
|
||||
@property (strong) NSDate *modDate;
|
||||
@@ -10,6 +8,6 @@
|
||||
|
||||
@interface ObjcUtils : NSObject
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
void install_global_handlers();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
#import <ZipArchive/ZipArchive.h>
|
||||
#endif
|
||||
#include <OpenGLES/ES3/gl.h>
|
||||
#include <OpenGLES/ES3/glext.h>
|
||||
@@ -31,7 +30,6 @@
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
#import <ZipArchive/ZipArchive.h>
|
||||
#endif
|
||||
#include <OpenGLES/ES3/gl.h>
|
||||
#include <OpenGLES/ES3/glext.h>
|
||||
@@ -42,7 +40,6 @@
|
||||
#ifdef __OBJC__
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <ZipArchive/ZipArchive.h>
|
||||
#endif
|
||||
#include <OpenGL/gl3.h>
|
||||
#include <OpenGL/gl3ext.h>
|
||||
|
||||
Reference in New Issue
Block a user