0

I am integrating the Firebase Crashlytics crash reporting framework into my iOS application. The application is written in ObjC and already has custom signal handlers so there comes the issue that I observe - if the application custom handlers are initialized after Firebase Crashlytics custom handlers - they do not fire, but Crashlytics handlers get fired. On the other hand, if my application handlers are registered first then all works as expected.

I inspected the Firebase Crashlytics code trying to find what might be reason why any later signals are not being fired but couldn't catch anything interesting.

Here's the code where signal is triggered by pressing the UI button. In fact I see the crash reported in Firebase Dashboard, but I don't see a file created by handler_1 nor I see the NSLog message.

#import "ViewController.h"
#import <signal.h>

@import Firebase;
@interface ViewController ()
@end

@implementation ViewController

static const int signals[] = {SIGSEGV, SIGFPE, SIGTRAP, SIGILL, SIGABRT, SIGPIPE, SIGBUS};
#define MAXSIG 14
struct sigaction handler_prev_1[MAXSIG];

void handler_1(int sig, siginfo_t* info, void* p) {
    NSString *someText = @"Random Text To Be Saved";
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *fileName = [[paths objectAtIndex:0]  stringByAppendingPathComponent:@"signal_handler.txt"];
    [someText writeToFile:fileName atomically:YES encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"Hello there!");
}

void register_handlers_1() {
    struct sigaction sa = {};
    sa.sa_sigaction = handler_1;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART | SA_SIGINFO;
    for (int i = 0; i < sizeof(signals)/sizeof(signals[0]); i++)
    {
        int res = sigaction(signals[i], &sa, &handler_prev_1[signals[i]]);
        NSLog(@"Registering signal %d handler = %d", signals[i], res);
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    // If I don't call this then the handler_1 is fired well
    [FIRApp configure];

    // Crashlytics is running a deffered signals check in (crashReportingSetupCompleted) after two seconds as I understand from their code,
    // so I am trying to avoid any unwanted interference with this 3 seconds sleep.
    [NSThread sleepForTimeInterval:3.000];

    register_handlers_1();

    UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(20, 50, 100, 30);
    [button setTitle:@"Crash" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(crashButtonTapped:)
        forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (IBAction)crashButtonTapped:(id)sender {
    *(volatile int*)0 = 0;
}
Alex
  • 163
  • 7
  • Crashlytics support here - to my knowledge, iOS has a requirement that you can only have one exception handler at a time. If it's working now when you initialize Crashlytics after your own, that seems it would be more circumstantial and not expected. In any case, as a hard requirement for Crashlytics to work, Crashlytics is probably not restoring the exception handler for you to use (at least in the way you've configured everything). – Kevin Kokomani Apr 02 '20 at 18:43
  • Thanks for the input @KevinKokomani I have been told that there is something to do with the Mach exception handlers registered by the Crashlytics. If the handlers are not registered - then both signal handlers are working fine. However I was not able to find any official reference in the Apple docs or else :( – Alex Apr 06 '20 at 13:00
  • Yeah, unfortunately it seems like this case generally shouldn't work that well, and that's what we've seen from other customers as well. If you're able to get this working in a consistent way that would be really interesting to hear about though. – Kevin Kokomani Apr 07 '20 at 16:50

0 Answers0