recover from exception on iOS and macOS using signals and log the stacktrace

This commit is contained in:
2018-10-04 15:26:18 +02:00
parent f45eefe433
commit 55dbab498f
7 changed files with 53 additions and 64 deletions

View File

@@ -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;
}

View File

@@ -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",

View File

@@ -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];

View File

@@ -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]));
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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>