Skip to content

Commit 31e054a

Browse files
authored
Crashlytics add new Record Exception Model API (#5055)
1 parent 956fb1b commit 31e054a

32 files changed

+699
-188
lines changed

Crashlytics/Crashlytics/Components/FIRCLSContext.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@
3333

3434
__BEGIN_DECLS
3535

36+
#ifdef __OBJC__
37+
@class FIRCLSInternalReport;
38+
@class FIRCLSSettings;
39+
@class FIRCLSInstallIdentifierModel;
40+
@class FIRCLSFileManager;
41+
#endif
42+
3643
typedef struct {
3744
volatile bool initialized;
3845
volatile bool debuggerAttached;
@@ -90,10 +97,18 @@ typedef struct {
9097
uint32_t maxKeyValues;
9198
} FIRCLSContextInitData;
9299

93-
bool FIRCLSContextInitialize(const FIRCLSContextInitData* initData);
100+
#ifdef __OBJC__
101+
bool FIRCLSContextInitialize(FIRCLSInternalReport* report,
102+
FIRCLSSettings* settings,
103+
FIRCLSInstallIdentifierModel* installIDModel,
104+
FIRCLSFileManager* fileManager);
94105

95106
// Re-writes the metadata file on the current thread
96-
void FIRCLSContextUpdateMetadata(const FIRCLSContextInitData* initData);
107+
void FIRCLSContextUpdateMetadata(FIRCLSInternalReport* report,
108+
FIRCLSSettings* settings,
109+
FIRCLSInstallIdentifierModel* installIDModel,
110+
FIRCLSFileManager* fileManager);
111+
#endif
97112

98113
void FIRCLSContextBaseInit(void);
99114
void FIRCLSContextBaseDeinit(void);

Crashlytics/Crashlytics/Components/FIRCLSContext.m

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717
#include <stdlib.h>
1818
#include <string.h>
1919

20+
#import "FIRCLSFileManager.h"
21+
#import "FIRCLSInstallIdentifierModel.h"
22+
#import "FIRCLSInternalReport.h"
23+
#import "FIRCLSSettings.h"
24+
2025
#include "FIRCLSApplication.h"
2126
#include "FIRCLSCrashedMarkerFile.h"
2227
#include "FIRCLSDefines.h"
2328
#include "FIRCLSFeatures.h"
2429
#include "FIRCLSGlobals.h"
25-
#include "FIRCLSInternalReport.h"
2630
#include "FIRCLSProcess.h"
2731
#include "FIRCLSUtility.h"
2832

@@ -45,7 +49,61 @@
4549
static const char* FIRCLSContextAppendToRoot(NSString* root, NSString* component);
4650
static void FIRCLSContextAllocate(FIRCLSContext* context);
4751

48-
bool FIRCLSContextInitialize(const FIRCLSContextInitData* initData) {
52+
FIRCLSContextInitData FIRCLSContextBuildInitData(FIRCLSInternalReport* report,
53+
FIRCLSSettings* settings,
54+
FIRCLSInstallIdentifierModel* installIDModel,
55+
FIRCLSFileManager* fileManager) {
56+
// Because we need to start the crash reporter right away,
57+
// it starts up either with default settings, or cached settings
58+
// from the last time they were fetched
59+
60+
FIRCLSContextInitData initData;
61+
62+
memset(&initData, 0, sizeof(FIRCLSContextInitData));
63+
64+
initData.customBundleId = nil;
65+
initData.installId = [installIDModel.installID UTF8String];
66+
initData.sessionId = [[report identifier] UTF8String];
67+
initData.rootPath = [[report path] UTF8String];
68+
initData.previouslyCrashedFileRootPath = [[fileManager rootPath] UTF8String];
69+
initData.errorsEnabled = [settings errorReportingEnabled];
70+
initData.customExceptionsEnabled = [settings customExceptionsEnabled];
71+
initData.maxCustomExceptions = [settings maxCustomExceptions];
72+
initData.maxErrorLogSize = [settings errorLogBufferSize];
73+
initData.maxLogSize = [settings logBufferSize];
74+
initData.maxKeyValues = [settings maxCustomKeys];
75+
76+
// If this is set, then we could attempt to do a synchronous submission for certain kinds of
77+
// events (exceptions). This is a very cool feature, but adds complexity to the backend. For now,
78+
// we're going to leave this disabled. It does work in the exception case, but will ultimtely
79+
// result in the following crash to be discared. Usually that crash isn't interesting. But, if it
80+
// was, we'd never have a chance to see it.
81+
initData.delegate = nil;
82+
83+
#if CLS_MACH_EXCEPTION_SUPPORTED
84+
__block exception_mask_t mask = 0;
85+
86+
// TODO(b/141241224) This if statement was hardcoded to no, so this block was never run
87+
// FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) {
88+
// if ([self.delegate ensureDeliveryOfUnixSignal:signal]) {
89+
// mask |= FIRCLSMachExceptionMaskForSignal(signal);
90+
// }
91+
// });
92+
93+
initData.machExceptionMask = mask;
94+
#endif
95+
96+
return initData;
97+
}
98+
99+
bool FIRCLSContextInitialize(FIRCLSInternalReport* report,
100+
FIRCLSSettings* settings,
101+
FIRCLSInstallIdentifierModel* installIDModel,
102+
FIRCLSFileManager* fileManager) {
103+
FIRCLSContextInitData initDataObj =
104+
FIRCLSContextBuildInitData(report, settings, installIDModel, fileManager);
105+
FIRCLSContextInitData* initData = &initDataObj;
106+
49107
if (!initData) {
50108
return false;
51109
}
@@ -197,7 +255,14 @@ bool FIRCLSContextInitialize(const FIRCLSContextInitData* initData) {
197255
return true;
198256
}
199257

200-
void FIRCLSContextUpdateMetadata(const FIRCLSContextInitData* initData) {
258+
void FIRCLSContextUpdateMetadata(FIRCLSInternalReport* report,
259+
FIRCLSSettings* settings,
260+
FIRCLSInstallIdentifierModel* installIDModel,
261+
FIRCLSFileManager* fileManager) {
262+
FIRCLSContextInitData initDataObj =
263+
FIRCLSContextBuildInitData(report, settings, installIDModel, fileManager);
264+
FIRCLSContextInitData* initData = &initDataObj;
265+
201266
NSString* rootPath = [NSString stringWithUTF8String:initData->rootPath];
202267

203268
const char* metaDataPath =

Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.m

Lines changed: 4 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -445,9 +445,7 @@ - (void)checkAndRotateInstallUUIDIfNeededWithReport:(FIRCLSInternalReport *)repo
445445
return;
446446
}
447447

448-
FIRCLSContextInitData initData = [self initializeContextInitData:report];
449-
450-
FIRCLSContextUpdateMetadata(&initData);
448+
FIRCLSContextUpdateMetadata(report, self.settings, self.installIDModel, self->_fileManager);
451449
}];
452450
}
453451

@@ -473,53 +471,18 @@ - (void)startNetworkRequestsWithToken:(FIRCLSDataCollectionToken *)token
473471
[self handleContentsInOtherReportingDirectoriesWithToken:token];
474472
}
475473

476-
- (FIRCLSContextInitData)initializeContextInitData:(FIRCLSInternalReport *)report {
477-
FIRCLSContextInitData initData;
478-
479-
memset(&initData, 0, sizeof(FIRCLSContextInitData));
480-
481-
// Because we need to start the crash reporter right away,
482-
// it starts up either with default settings, or cached settings
483-
// from the last time they were fetched
484-
FIRCLSSettings *settings = self.settings;
485-
486-
initData.customBundleId = NULL;
487-
initData.installId = [self.installIDModel.installID UTF8String];
488-
initData.sessionId = [[report identifier] UTF8String];
489-
initData.rootPath = [[report path] UTF8String];
490-
initData.previouslyCrashedFileRootPath = [[_fileManager rootPath] UTF8String];
491-
#if CLS_MACH_EXCEPTION_SUPPORTED
492-
initData.machExceptionMask = [self machExceptionMask];
493-
#endif
494-
initData.errorsEnabled = [settings errorReportingEnabled];
495-
initData.customExceptionsEnabled = [settings customExceptionsEnabled];
496-
initData.maxCustomExceptions = [settings maxCustomExceptions];
497-
initData.maxErrorLogSize = [settings errorLogBufferSize];
498-
initData.maxLogSize = [settings logBufferSize];
499-
initData.maxKeyValues = [settings maxCustomKeys];
500-
501-
return initData;
502-
}
503-
504474
- (BOOL)startCrashReporterWithProfilingMark:(FIRCLSProfileMark)mark
505475
report:(FIRCLSInternalReport *)report {
506476
if (!report) {
507477
return NO;
508478
}
509479

510-
FIRCLSContextInitData initData = [self initializeContextInitData:report];
511-
512-
// If this is set, then we could attempt to do a synchronous submission for certain kinds of
513-
// events (exceptions). This is a very cool feature, but adds complexity to the backend. For now,
514-
// we're going to leave this disabled. It does work in the exception case, but will ultimtely
515-
// result in the following crash to be discared. Usually that crash isn't interesting. But, if it
516-
// was, we'd never have a chance to see it.
517-
initData.delegate = NULL;
518-
519-
if (![self installCrashReportingHandlers:&initData]) {
480+
if (!FIRCLSContextInitialize(report, self.settings, self.installIDModel, _fileManager)) {
520481
return NO;
521482
}
522483

484+
[self setupStateNotifications];
485+
523486
[self registerAnalyticsEventListener];
524487

525488
[self crashReportingSetupCompleted:mark];
@@ -569,33 +532,8 @@ - (FIRCLSReportUploader *)uploader {
569532
return _uploader;
570533
}
571534

572-
#if CLS_MACH_EXCEPTION_SUPPORTED
573-
- (exception_mask_t)machExceptionMask {
574-
__block exception_mask_t mask = 0;
575-
576-
// TODO(b/141241224) This if statement was hardcoded to no, so this block was never run
577-
// FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) {
578-
// if ([self.delegate ensureDeliveryOfUnixSignal:signal]) {
579-
// mask |= FIRCLSMachExceptionMaskForSignal(signal);
580-
// }
581-
// });
582-
583-
return mask;
584-
}
585-
#endif
586-
587535
#pragma mark - Reporting Lifecycle
588536

589-
- (BOOL)installCrashReportingHandlers:(FIRCLSContextInitData *)initData {
590-
if (!FIRCLSContextInitialize(initData)) {
591-
return NO;
592-
}
593-
594-
[self setupStateNotifications];
595-
596-
return YES;
597-
}
598-
599537
- (FIRCLSInternalReport *)setupCurrentReport:(NSString *)executionIdentifier {
600538
[self createLaunchFailureMarker];
601539

Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#import "FIRCLSReportManager.h"
1616
#import "FIRCLSReportUploader.h"
1717

18+
@class FIRCLSInstallIdentifierModel;
19+
1820
@interface FIRCLSReportManager () <FIRCLSReportUploaderDelegate, FIRCLSReportUploaderDataSource>
1921

2022
@property(nonatomic, strong) NSOperationQueue *operationQueue;

Crashlytics/Crashlytics/FIRCrashlytics.m

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,8 @@ - (void)recordError:(NSError *)error {
307307
FIRCLSUserLoggingRecordError(error, nil);
308308
}
309309

310-
- (void)recordCustomExceptionName:(NSString *)name
311-
reason:(NSString *)reason
312-
frameArray:(NSArray<FIRCLSStackFrame *> *)frameArray {
313-
FIRCLSExceptionRecord(FIRCLSExceptionTypeCustom, [[name copy] UTF8String],
314-
[[reason copy] UTF8String], [frameArray copy], NO);
310+
- (void)recordExceptionModel:(FIRExceptionModel *)exceptionModel {
311+
FIRCLSExceptionRecordModel(exceptionModel);
315312
}
316313

317314
@end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2020 Google
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#import "FIRExceptionModel.h"
16+
17+
@interface FIRExceptionModel ()
18+
19+
@property(nonatomic, copy) NSString *name;
20+
@property(nonatomic, copy) NSString *reason;
21+
22+
@end
23+
24+
@implementation FIRExceptionModel
25+
26+
- (instancetype)initWithName:(NSString *)name reason:(NSString *)reason {
27+
self = [super init];
28+
if (!self) {
29+
return nil;
30+
}
31+
32+
_name = [name copy];
33+
_reason = [reason copy];
34+
35+
return self;
36+
}
37+
38+
+ (instancetype)exceptionModelWithName:(NSString *)name reason:(NSString *)reason {
39+
return [[FIRExceptionModel alloc] initWithName:name reason:reason];
40+
}
41+
42+
@end
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright 2020 Google
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#import "FIRStackFrame_Private.h"
16+
17+
@interface FIRStackFrame ()
18+
19+
@property(nonatomic, copy, nullable) NSString *symbol;
20+
@property(nonatomic, copy, nullable) NSString *rawSymbol;
21+
@property(nonatomic, copy, nullable) NSString *library;
22+
@property(nonatomic, copy, nullable) NSString *fileName;
23+
@property(nonatomic, assign) uint32_t lineNumber;
24+
@property(nonatomic, assign) uint64_t offset;
25+
@property(nonatomic, assign) uint64_t address;
26+
27+
@property(nonatomic, assign) BOOL isSymbolicated;
28+
29+
@end
30+
31+
@implementation FIRStackFrame
32+
33+
#pragma mark - Public Methods
34+
35+
- (instancetype)initWithSymbol:(NSString *)symbol file:(NSString *)file line:(NSInteger)line {
36+
self = [super init];
37+
if (!self) {
38+
return nil;
39+
}
40+
41+
_symbol = [symbol copy];
42+
_fileName = [file copy];
43+
_lineNumber = (uint32_t)line;
44+
45+
_isSymbolicated = true;
46+
47+
return self;
48+
}
49+
50+
+ (instancetype)stackFrameWithSymbol:(NSString *)symbol file:(NSString *)file line:(NSInteger)line {
51+
return [[FIRStackFrame alloc] initWithSymbol:symbol file:file line:line];
52+
}
53+
54+
#pragma mark - Internal Methods
55+
56+
+ (instancetype)stackFrame {
57+
return [[self alloc] init];
58+
}
59+
60+
+ (instancetype)stackFrameWithAddress:(NSUInteger)address {
61+
FIRStackFrame *frame = [self stackFrame];
62+
63+
[frame setAddress:address];
64+
65+
return frame;
66+
}
67+
68+
+ (instancetype)stackFrameWithSymbol:(NSString *)symbol {
69+
FIRStackFrame *frame = [self stackFrame];
70+
71+
frame.symbol = symbol;
72+
frame.rawSymbol = symbol;
73+
74+
return frame;
75+
}
76+
77+
#pragma mark - Overrides
78+
79+
- (NSString *)description {
80+
if (self.isSymbolicated) {
81+
return [NSString
82+
stringWithFormat:@"{%@ - %@:%u}", [self fileName], [self symbol], [self lineNumber]];
83+
}
84+
85+
if (self.fileName) {
86+
return [NSString stringWithFormat:@"{[0x%llx] %@ - %@:%u}", [self address], [self fileName],
87+
[self symbol], [self lineNumber]];
88+
}
89+
90+
return [NSString
91+
stringWithFormat:@"{[0x%llx + %u] %@}", [self address], [self lineNumber], [self symbol]];
92+
}
93+
94+
@end

0 commit comments

Comments
 (0)