Skip to content

Commit 20daa45

Browse files
authored
Fix possible deadlock in urgent state of report uploader (#9826)
Add forgotten semaphore_signal calls at early return
1 parent be5f1fe commit 20daa45

File tree

4 files changed

+48
-12
lines changed

4 files changed

+48
-12
lines changed

Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,14 @@ - (void)uploadPackagedReportAtPath:(NSString *)path
191191
if (!wasWritten) {
192192
FIRCLSErrorLog(
193193
@"Failed to send crash report due to failure writing GoogleDataTransport event");
194+
dispatch_semaphore_signal(semaphore);
194195
return;
195196
}
196197

197198
if (error) {
198199
FIRCLSErrorLog(@"Failed to send crash report due to GoogleDataTransport error: %@",
199200
error.localizedDescription);
201+
dispatch_semaphore_signal(semaphore);
200202
return;
201203
}
202204

Crashlytics/UnitTests/FIRCLSReportUploaderTests.m

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ - (void)setUp {
5959
self.mockDataTransport = [[FIRMockGDTCORTransport alloc] initWithMappingID:@"1206"
6060
transformers:nil
6161
target:kGDTCORTargetCSH];
62+
self.mockDataTransport.sendDataEvent_wasWritten = YES;
6263
self.fileManager = [[FIRCLSTempMockFileManager alloc] init];
6364

6465
id fakeApp = [[FIRAppFake alloc] init];
@@ -114,17 +115,46 @@ - (void)testUrgentUploadPackagedReportWithPath {
114115
[self runUploadPackagedReportWithUrgency:YES];
115116
}
116117

117-
- (void)testUploadPackagedReportWithoutDataCollectionToken {
118-
[self setUpForUpload];
118+
- (void)testUrgentWaitUntillUpload {
119+
self.mockDataTransport.async = YES;
120+
121+
[self runUploadPackagedReportWithUrgency:YES];
122+
123+
XCTAssertNotNil(self.mockDataTransport.sendDataEvent_event);
124+
}
125+
126+
- (void)testUrgentWaitUntillUploadWithError {
127+
self.mockDataTransport.async = YES;
128+
self.mockDataTransport.sendDataEvent_error = [[NSError alloc] initWithDomain:@"domain"
129+
code:1
130+
userInfo:nil];
131+
132+
[self.uploader uploadPackagedReportAtPath:[self packagePath]
133+
dataCollectionToken:FIRCLSDataCollectionToken.validToken
134+
asUrgent:YES];
135+
136+
XCTAssertNotNil(self.mockDataTransport.sendDataEvent_event);
137+
}
138+
139+
- (void)testUrgentWaitUntillUploadWithWritingError {
140+
self.mockDataTransport.async = YES;
141+
self.mockDataTransport.sendDataEvent_wasWritten = NO;
119142

143+
[self.uploader uploadPackagedReportAtPath:[self packagePath]
144+
dataCollectionToken:FIRCLSDataCollectionToken.validToken
145+
asUrgent:YES];
146+
147+
XCTAssertNotNil(self.mockDataTransport.sendDataEvent_event);
148+
}
149+
150+
- (void)testUploadPackagedReportWithoutDataCollectionToken {
120151
[self.uploader uploadPackagedReportAtPath:[self packagePath] dataCollectionToken:nil asUrgent:NO];
121152

122153
// Ensure we don't hand off an event to GDT
123154
XCTAssertNil(self.mockDataTransport.sendDataEvent_event);
124155
}
125156

126157
- (void)testUploadPackagedReportNotGDTWritten {
127-
[self setUpForUpload];
128158
self.mockDataTransport.sendDataEvent_wasWritten = NO;
129159

130160
[self.uploader uploadPackagedReportAtPath:[self packagePath] dataCollectionToken:nil asUrgent:NO];
@@ -134,7 +164,6 @@ - (void)testUploadPackagedReportNotGDTWritten {
134164
}
135165

136166
- (void)testUploadPackagedReportGDTError {
137-
[self setUpForUpload];
138167
self.mockDataTransport.sendDataEvent_error = [[NSError alloc] initWithDomain:@"domain"
139168
code:1
140169
userInfo:nil];
@@ -152,8 +181,6 @@ - (NSString *)packagePath {
152181
}
153182

154183
- (void)runUploadPackagedReportWithUrgency:(BOOL)urgent {
155-
[self setUpForUpload];
156-
157184
[self.uploader uploadPackagedReportAtPath:[self packagePath]
158185
dataCollectionToken:FIRCLSDataCollectionToken.validToken
159186
asUrgent:urgent];
@@ -162,8 +189,4 @@ - (void)runUploadPackagedReportWithUrgency:(BOOL)urgent {
162189
XCTAssertEqualObjects(self.fileManager.removedItemAtPath_path, [self packagePath]);
163190
}
164191

165-
- (void)setUpForUpload {
166-
self.mockDataTransport.sendDataEvent_wasWritten = YES;
167-
}
168-
169192
@end

Crashlytics/UnitTests/Mocks/FIRMockGDTCoreTransport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
2424
@property(nullable, nonatomic, strong) GDTCOREvent *sendDataEvent_event;
2525
@property(nullable, nonatomic, strong) NSError *sendDataEvent_error;
2626
@property(nonatomic) BOOL sendDataEvent_wasWritten;
27+
@property(assign, nonatomic) BOOL async;
2728

2829
- (instancetype)initWithMappingID:(NSString *)mappingID
2930
transformers:(nullable NSArray<id<GDTCOREventTransformer>> *)transformers

Crashlytics/UnitTests/Mocks/FIRMockGDTCoreTransport.m

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,24 @@ - (instancetype)initWithMappingID:(NSString *)mappingID
2222
_mappingID = mappingID;
2323
_target = target;
2424
_sendDataEvent_wasWritten = YES;
25+
_async = NO;
2526

2627
return [super initWithMappingID:mappingID transformers:transformers target:target];
2728
}
2829

2930
- (void)sendDataEvent:(GDTCOREvent *)event
3031
onComplete:(void (^)(BOOL wasWritten, NSError *error))completion {
31-
self.sendDataEvent_event = event;
32-
completion(self.sendDataEvent_wasWritten, self.sendDataEvent_error);
32+
dispatch_block_t sendData = ^() {
33+
self.sendDataEvent_event = event;
34+
completion(self.sendDataEvent_wasWritten, self.sendDataEvent_error);
35+
};
36+
37+
if (self.async) {
38+
dispatch_after(DISPATCH_TIME_NOW, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
39+
sendData);
40+
} else {
41+
sendData();
42+
}
3343
}
3444

3545
@end

0 commit comments

Comments
 (0)