-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[ios] Fix a race condition issue in the Mapbox metrics class. #15029
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,9 +65,13 @@ - (NSURLSessionConfiguration *)defaultSessionConfiguration { | |
} | ||
|
||
- (void)startDownloadEvent:(NSString *)urlString type:(NSString *)resourceType { | ||
if (urlString && ![self.events objectForKey:urlString]) { | ||
[self.events setObject:@{ MGLStartTime: [NSDate date], MGLResourceType: resourceType } forKey:urlString]; | ||
NSString *retainedUrlString = urlString; | ||
NSString *retainedResourceType = resourceType; | ||
if (retainedUrlString && !self.events[retainedUrlString]) { | ||
self.events[retainedUrlString] = @{ MGLStartTime: [NSDate date], MGLResourceType: retainedResourceType }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we need to change the events property to be atomic:
since reading/writing/deleting could happen at the same time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This property gets called multiple times. I consider the atomicity but in practice found no reason to make this an atomic property when the crash is raised for a different reason. |
||
} | ||
retainedUrlString = nil; | ||
retainedResourceType = nil; | ||
} | ||
|
||
- (void)stopDownloadEventForResponse:(NSURLResponse *)response { | ||
|
@@ -80,15 +84,16 @@ - (void)cancelDownloadEventForResponse:(NSURLResponse *)response { | |
|
||
- (void)sendEventForURLResponse:(NSURLResponse *)response withAction:(NSString *)action | ||
{ | ||
if ([response isKindOfClass:[NSURLResponse class]]) { | ||
NSString *urlString = response.URL.relativePath; | ||
NSURLResponse *retainedResponse = response; | ||
if ([retainedResponse isKindOfClass:[NSURLResponse class]]) { | ||
NSString *urlString = retainedResponse.URL.relativePath; | ||
if (urlString && [self.events objectForKey:urlString]) { | ||
NSDictionary *eventAttributes = [self eventAttributesForURL:response withAction:action]; | ||
NSDictionary *eventAttributes = [self eventAttributesForURL:retainedResponse withAction:action]; | ||
[self.metricsDelegate networkConfiguration:self didGenerateMetricEvent:eventAttributes]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should dispatch this delegate call on the main queue. |
||
[self.events removeObjectForKey:urlString]; | ||
} | ||
} | ||
|
||
retainedResponse = nil; | ||
} | ||
|
||
- (NSDictionary *)eventAttributesForURL:(NSURLResponse *)response withAction:(NSString *)action | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is sufficient. AFAIK
urlString
should be retained by this method anyway - how about usingcopy
here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I consider using copy but an increase in the retain count would do the job better.