Skip to content

Commit

Permalink
Merge pull request #1271 from bugsnag/release-v6.15.2
Browse files Browse the repository at this point in the history
Release v6.15.2
  • Loading branch information
nickdowell authored Jan 5, 2022
2 parents 45e05a2 + 6a81ae3 commit 46ecccb
Show file tree
Hide file tree
Showing 86 changed files with 879 additions and 408 deletions.
24 changes: 16 additions & 8 deletions .buildkite/pipeline.full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ steps:
plugins:
artifacts#v1.3.0:
download: ["features/fixtures/ios/output/iOSTestApp.ipa"]
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=/app/build/iOSTestApp.ipa"
Expand All @@ -42,7 +43,8 @@ steps:
plugins:
artifacts#v1.3.0:
download: ["features/fixtures/ios/output/iOSTestApp.ipa"]
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=/app/build/iOSTestApp.ipa"
Expand All @@ -69,7 +71,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=@build/ipa_url.txt"
Expand Down Expand Up @@ -97,7 +100,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=@build/ipa_url.txt"
Expand Down Expand Up @@ -125,7 +129,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=@build/ipa_url.txt"
Expand Down Expand Up @@ -153,7 +158,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=@build/ipa_url.txt"
Expand Down Expand Up @@ -183,7 +189,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=@build/ipa_url.txt"
Expand Down Expand Up @@ -213,7 +220,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=@build/ipa_url.txt"
Expand Down
12 changes: 8 additions & 4 deletions .buildkite/pipeline.quick.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=@build/ipa_url.txt"
Expand Down Expand Up @@ -172,7 +173,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=@build/ipa_url.txt"
Expand Down Expand Up @@ -200,7 +202,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=@build/ipa_url.txt"
Expand Down Expand Up @@ -228,7 +231,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "--app=@build/ipa_url.txt"
Expand Down
6 changes: 4 additions & 2 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "features/barebone_tests.feature"
Expand All @@ -163,7 +164,8 @@ steps:
artifacts#v1.3.0:
download: "features/fixtures/ios/output/ipa_url.txt"
upload: "maze_output/failed/**/*"
docker-compose#v3.3.0:
docker-compose#v3.7.0:
pull: cocoa-maze-runner
run: cocoa-maze-runner
command:
- "features/barebone_tests.feature"
Expand Down
4 changes: 2 additions & 2 deletions .jazzy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ author_url: "https://www.bugsnag.com"
author: "Bugsnag Inc"
clean: false # avoid deleting docs/.git
framework_root: "Bugsnag"
github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.15.1/Bugsnag"
github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.15.2/Bugsnag"
github_url: "https://github.com/bugsnag/bugsnag-cocoa"
hide_documentation_coverage: true
module: "Bugsnag"
module_version: "6.15.1"
module_version: "6.15.2"
objc: true
output: "docs"
readme: "README.md"
Expand Down
4 changes: 2 additions & 2 deletions Bugsnag.podspec.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Bugsnag",
"version": "6.15.1",
"version": "6.15.2",
"summary": "The Bugsnag crash reporting framework for Apple platforms.",
"homepage": "https://bugsnag.com",
"license": "MIT",
Expand All @@ -9,7 +9,7 @@
},
"source": {
"git": "https://github.com/bugsnag/bugsnag-cocoa.git",
"tag": "v6.15.1"
"tag": "v6.15.2"
},
"frameworks": [
"Foundation",
Expand Down
9 changes: 9 additions & 0 deletions Bugsnag/Delivery/BSGEventUploadKSCrashReportOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ - (BugsnagEvent *)loadEventAndReturnError:(NSError * __autoreleasing *)errorPtr
NSMutableDictionary *diagnostics = [NSMutableDictionary dictionary];
diagnostics[@"data"] = [data base64EncodedStringWithOptions:0];
diagnostics[@"file"] = self.file;
NSDictionary<NSFileAttributeKey, id> *fileAttributes = [NSFileManager.defaultManager attributesOfItemAtPath:self.file error:nil];
if (fileAttributes) {
NSDate *creationDate = fileAttributes[NSFileCreationDate];
NSDate *modificationDate = fileAttributes[NSFileModificationDate];
if (creationDate && modificationDate) {
// The amount of time spent writing the file could indicate why the process never completed
diagnostics[@"modificationInterval"] = @([modificationDate timeIntervalSinceDate:creationDate]);
}
}
ReportInternalError(@"JSON parsing error", BSGErrorDescription(error), diagnostics);
if (errorPtr) {
*errorPtr = error;
Expand Down
12 changes: 11 additions & 1 deletion Bugsnag/Delivery/BSGEventUploadOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,13 @@ - (void)runWithDelegate:(id<BSGEventUploadOperationDelegate>)delegate completion
return;
}

NSDictionary *_Nullable originalPayload = nil;
for (BugsnagOnSendErrorBlock block in configuration.onSendBlocks) {
@try {
if (!originalPayload) {
// If OnSendError modifies the event and delivery fails, we need to persist the original state of the event.
originalPayload = [event toJsonWithRedactedKeys:configuration.redactedKeys];
}
if (!block(event)) {
[self deleteEvent];
completionHandler();
Expand All @@ -98,6 +103,11 @@ - (void)runWithDelegate:(id<BSGEventUploadOperationDelegate>)delegate completion
return;
}

if ([originalPayload isEqual:eventPayload]) {
// Save memory if payload has not changed
originalPayload = nil;
}

NSString *apiKey = event.apiKey ?: configuration.apiKey;

NSMutableDictionary *requestPayload = [NSMutableDictionary dictionary];
Expand Down Expand Up @@ -131,7 +141,7 @@ - (void)runWithDelegate:(id<BSGEventUploadOperationDelegate>)delegate completion
case BugsnagApiClientDeliveryStatusFailed:
bsg_log_debug(@"Upload failed; will retry event %@", self.name);
if (self.shouldStoreEventPayloadForRetry) {
[delegate storeEventPayload:eventPayload];
[delegate storeEventPayload:originalPayload ?: eventPayload];
}
break;

Expand Down
53 changes: 53 additions & 0 deletions Bugsnag/Delivery/BSGEventUploader.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@
#import "BSGEventUploadKSCrashReportOperation.h"
#import "BSGEventUploadObjectOperation.h"
#import "BSGFileLocations.h"
#import "BSGInternalErrorReporter.h"
#import "BSGJSONSerialization.h"
#import "BSGUtils.h"
#import "BugsnagConfiguration.h"
#import "BugsnagEvent+Private.h"
#import "BugsnagLogger.h"


static NSString * const CrashReportPrefix = @"CrashReport-";
static NSString * const RecrashReportPrefix = @"RecrashReport-";


@interface BSGEventUploader () <BSGEventUploadOperationDelegate>

@property (readonly, nonatomic) NSString *eventsDirectory;
Expand Down Expand Up @@ -89,6 +94,7 @@ - (void)uploadStoredEvents {
}
bsg_log_debug(@"Will scan stored events");
[self.scanQueue addOperationWithBlock:^{
[self processRecrashReports];
NSMutableArray<NSString *> *sortedFiles = [self sortedEventFiles];
[self deleteExcessFiles:sortedFiles];
NSArray<BSGEventUploadFileOperation *> *operations = [self uploadOperationsWithFiles:sortedFiles];
Expand All @@ -105,6 +111,7 @@ - (void)uploadStoredEventsAfterDelay:(NSTimeInterval)delay {
}

- (void)uploadLatestStoredEvent:(void (^)(void))completionHandler {
[self processRecrashReports];
NSString *latestFile = [self sortedEventFiles].lastObject;
BSGEventUploadFileOperation *operation = latestFile ? [self uploadOperationsWithFiles:@[latestFile]].lastObject : nil;
if (!operation) {
Expand All @@ -118,6 +125,52 @@ - (void)uploadLatestStoredEvent:(void (^)(void))completionHandler {

// MARK: - Implementation

- (void)processRecrashReports {
NSError *error = nil;
NSString *directory = self.kscrashReportsDirectory;
NSFileManager *fileManager = [[NSFileManager alloc] init];

NSArray<NSString *> *entries = [fileManager contentsOfDirectoryAtPath:directory error:&error];
if (!entries) {
bsg_log_err(@"%@", error);
return;
}

// Limit to reporting a single recrash to prevent potential for consuming too many resources
BOOL didReportRecrash = NO;

for (NSString *filename in entries) {
if (![filename hasPrefix:RecrashReportPrefix] ||
![filename.pathExtension isEqual:@"json"]) {
continue;
}

NSString *path = [directory stringByAppendingPathComponent:filename];
if (!didReportRecrash) {
id recrashReport = [BSGJSONSerialization JSONObjectWithContentsOfFile:path options:0 error:&error];
if ([recrashReport isKindOfClass:[NSDictionary class]]) {
bsg_log_debug(@"Reporting %@", filename);
[BSGInternalErrorReporter.sharedInstance reportRecrash:recrashReport];
didReportRecrash = YES;
}
}
bsg_log_debug(@"Deleting %@", filename);
if (![fileManager removeItemAtPath:path error:&error]) {
bsg_log_err(@"%@", error);
}

// Delete the report to prevent reporting a "JSON parsing error"
NSString *crashReportFilename = [filename stringByReplacingOccurrencesOfString:RecrashReportPrefix withString:CrashReportPrefix];
NSString *crashReportPath = [directory stringByAppendingPathComponent:crashReportFilename];
if (![BSGJSONSerialization JSONObjectWithContentsOfFile:crashReportPath options:0 error:nil]) {
bsg_log_info(@"Deleting unparsable %@", crashReportFilename);
if (![fileManager removeItemAtPath:crashReportPath error:&error]) {
bsg_log_err(@"%@", error);
}
}
}
}

/// Returns the stored event files sorted from oldest to most recent.
- (NSMutableArray<NSString *> *)sortedEventFiles {
NSMutableArray<NSString *> *files = [NSMutableArray array];
Expand Down
12 changes: 8 additions & 4 deletions Bugsnag/Helpers/BSGAppHangDetector.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
@interface BSGAppHangDetector ()

@property (weak, nonatomic) id<BSGAppHangDetectorDelegate> delegate;
@property (nonatomic) BOOL runLoopIsRunning;
@property (nonatomic) BOOL recordAllThreads;
@property (nonatomic) CFRunLoopObserverRef observer;
@property (atomic) dispatch_time_t processingDeadline;
Expand Down Expand Up @@ -81,6 +82,7 @@ - (void)startWithDelegate:(id<BSGAppHangDetectorDelegate>)delegate {
// Each iteration indicates a separate unit of work so the hang detection should be reset accordingly.
dispatch_semaphore_signal(self.processingFinished);
}
self.runLoopIsRunning = YES;
self.processingDeadline = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(threshold * NSEC_PER_SEC));
dispatch_semaphore_signal(self.processingStarted);
isProcessing = YES;
Expand All @@ -104,9 +106,9 @@ - (void)startWithDelegate:(id<BSGAppHangDetectorDelegate>)delegate {
self.observer = CFRunLoopObserverCreateWithHandler(NULL, activities, true, order, observerBlock);

// Start monitoring immediately so that app hangs during launch can be detected.
// Note that because scene-based apps start in UIApplicationStateBackground, hangs in
// -[AppDelegate application:didFinishLaunchingWithOptions:] will be ignored.
observerBlock(self.observer, kCFRunLoopAfterWaiting);
self.processingDeadline = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(threshold * NSEC_PER_SEC));
dispatch_semaphore_signal(self.processingStarted);
isProcessing = YES;

CFRunLoopAddObserver(CFRunLoopGetMain(), self.observer, kCFRunLoopCommonModes);

Expand Down Expand Up @@ -146,7 +148,9 @@ - (void)detectAppHangs {
}
#endif

if (shouldReportAppHang && !bsg_kscrashstate_currentState()->applicationIsInForeground) {
// Ignore background state if the runloop has not yet ticked so that hangs in `didFinishLaunching` in UIScene-based
// apps are detected. UIScene-based apps always start in UIApplicationStateBackground, unlike those without scenes.
if (shouldReportAppHang && !bsg_kscrashstate_currentState()->applicationIsInForeground && self.runLoopIsRunning) {
bsg_log_debug(@"Ignoring app hang because app is in the background");
shouldReportAppHang = NO;
}
Expand Down
6 changes: 4 additions & 2 deletions Bugsnag/Helpers/BSGInternalErrorReporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ FOUNDATION_EXPORT NSString *BSGErrorDescription(NSError *error);

@property (readonly, nonatomic) BugsnagConfiguration *configuration;

@property (readonly, nonatomic) BugsnagNotifier *notifier;

- (BugsnagAppWithState *)generateAppWithState:(NSDictionary *)systemInfo;

- (BugsnagDeviceWithState *)generateDeviceWithState:(NSDictionary *)systemInfo;
Expand Down Expand Up @@ -62,6 +60,8 @@ FOUNDATION_EXPORT NSString *BSGErrorDescription(NSError *error);
diagnostics:(nullable NSDictionary<NSString *, id> *)diagnostics
groupingHash:(nullable NSString *)groupingHash;

- (void)reportRecrash:(NSDictionary *)recrashReport;

// Private

- (nullable BugsnagEvent *)eventWithErrorClass:(NSString *)errorClass
Expand All @@ -73,6 +73,8 @@ FOUNDATION_EXPORT NSString *BSGErrorDescription(NSError *error);
diagnostics:(nullable NSDictionary<NSString *, id> *)diagnostics
groupingHash:(nullable NSString *)groupingHash;

- (nullable BugsnagEvent *)eventWithRecrashReport:(NSDictionary *)recrashReport;

- (nullable NSURLRequest *)requestForEvent:(BugsnagEvent *)event error:(NSError * __autoreleasing *)errorPtr;

@end
Expand Down
Loading

0 comments on commit 46ecccb

Please sign in to comment.