Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[ios] Fix a race condition issue in the Mapbox metrics class. #15029

Closed
wants to merge 2 commits into from

Conversation

fabian-guerra
Copy link
Contributor

@fabian-guerra fabian-guerra commented Jun 29, 2019

Fixes #14982

Downloading multiple offline packs starts multiple background requests. The metrics controller we were using used a property from a URL object in an autoreleased pool. This request may go away in the middle of setting the starting event, which may have caused the crash.

I think is unnecessary to use a lock for the urlString variable. instead I'm retaining the variable to avoid passing nil to the events dictionary.

/cc @friedbunny

@fabian-guerra fabian-guerra added iOS Mapbox Maps SDK for iOS crash needs changelog Indicates PR needs a changelog entry prior to merging. labels Jun 29, 2019
@fabian-guerra fabian-guerra added this to the release-p milestone Jun 29, 2019
@fabian-guerra fabian-guerra requested a review from 1ec5 as a code owner June 29, 2019 16:43
@fabian-guerra fabian-guerra requested a review from a team June 29, 2019 16:43
@fabian-guerra fabian-guerra self-assigned this Jun 29, 2019
@@ -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;
Copy link
Contributor

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 using copy here?

Copy link
Contributor Author

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.

NSString *retainedUrlString = urlString;
NSString *retainedResourceType = resourceType;
if (retainedUrlString && !self.events[retainedUrlString]) {
self.events[retainedUrlString] = @{ MGLStartTime: [NSDate date], MGLResourceType: retainedResourceType };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to change the events property to be atomic:

@property (atomic, strong) NSMutableDictionary<NSString*, NSDictionary*> *events;

since reading/writing/deleting could happen at the same time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

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];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should dispatch this delegate call on the main queue.

@fabian-guerra fabian-guerra removed the needs changelog Indicates PR needs a changelog entry prior to merging. label Jul 1, 2019
@friedbunny
Copy link
Contributor

  • Studio Preview does not use offline packs and saw this crash, so I’m not sure the explanation/changelog is completely accurate.
  • Are there tests that can be added to make sure this does not regress?
  • Can this logic be made conditional on there being a consumer of these metrics?

@chloekraw
Copy link
Contributor

Closes #14982

@julianrex
Copy link
Contributor

Added #15113 to replace this PR.

@chloekraw
Copy link
Contributor

Per #15029 (comment), closing to avoid confusion

@chloekraw chloekraw closed this Jul 12, 2019
@friedbunny friedbunny assigned julianrex and unassigned friedbunny Jul 12, 2019
@julianrex
Copy link
Contributor

Can this logic be made conditional on there being a consumer of these metrics?

We have metricsManager:shouldHandleMetric: that ought to handle this, but looks like we need to move it earlier in the process.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
crash ⚠️ DO NOT MERGE Work in progress, proof of concept, or on hold iOS Mapbox Maps SDK for iOS needs tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Crash in -[MGLNetworkConfiguration startDownloadEvent:type:]
4 participants