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

[ios] Address bad access exception in MGLAttributionInfo #13300

Merged
merged 2 commits into from Nov 14, 2018

Conversation

jmkiley
Copy link
Contributor

@jmkiley jmkiley commented Nov 6, 2018

Continues discussion from #13298 in order to add the fix to master.

This PR addresses a bad access exception with MGLMapSnapshotter on iOS 8. Per Apple docs:

The HTML importer should not be called from a background thread (that is, the options dictionary includes NSDocumentTypeDocumentAttribute with a value of NSHTMLTextDocumentType). It will try to synchronize with the main thread, fail, and time out. Calling it from the main thread works (but can still time out if the HTML contains references to external resources, which should be avoided at all costs). The HTML import mechanism is meant for implementing something like markdown (that is, text styles, colors, and so on), not for general HTML import.

cc @julianrex @ChrisLoer

@jmkiley jmkiley added iOS Mapbox Maps SDK for iOS in progress labels Nov 6, 2018
@jmkiley jmkiley self-assigned this Nov 6, 2018
error:NULL];
__block NSMutableAttributedString *attributedString;

dispatch_sync(dispatch_get_main_queue() , ^{
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that this method is called as part of -[MGLTileSource attributionInfos], which is a public method that can be called at any time. Even internal uses of this method tend to occur in a for loop, since there are multiple sources to inspect at the same time.

If performance does turn out to be a problem, an alternative to blocking on the main thread here would be to do so further up the call stack, wherever it’s expected that the caller could be on a thread other than the main thread:

NSArray<MGLAttributionInfo *>* attributionInfo = [MGLMapSnapshotter generateAttributionInfos:attributions];

This would require documenting other callers, such as -[MGLTileSource attributionInfos], as needing to run on the main thread. There is precedent for such a requirement.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to check whether it's being called on the main queue. Would it be better to call the NSMutableAttributedString initializer earlier than to fiddle with queues? @julianrex and I found that the exception did not occur when we created an NSMutableAttributedString in the initializer for a map view.

Copy link
Contributor

Choose a reason for hiding this comment

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

@julianrex and I found that the exception did not occur when we created an NSMutableAttributedString in the initializer for a map view.

We can't rely on that behavior as it's not documented.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry if I'm just parading my iOS ignorance here, but isn't MGLMapView essentially required to be created and used on the main thread? And if that's the case then creating the attributed string in the initializer should be good, right?

If we can find a way to avoid "fiddling with queues" we should. It's not the queues themselves that are the problem -- but hidden/unexpected cross-thread blocking calls are trouble.

Copy link
Contributor

Choose a reason for hiding this comment

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

@ChrisLoer @jmkiley was referring to the fact that we can avoid the crash if we initialize any old NSMutableAttributedString on the main thread (it ends up calling WebKitInitialize using a dispatch_once - I suspect it's that initializer that needs to be on the main thread) - not the specific one.

@julianrex julianrex requested review from julianrex and removed request for julianrex November 8, 2018 15:56
@jmkiley
Copy link
Contributor Author

jmkiley commented Nov 12, 2018

This PR currently checks whether the NSMutableAttributedString is being initialized on the main thread.

@jmkiley
Copy link
Contributor Author

jmkiley commented Nov 12, 2018

Addressed a memory leak that popped up during profiling. Thank you @fabian-guerra for walking through the Instruments trace with me.

dispatch_sync(dispatch_get_main_queue(), initialization);
} else {
initialization();
}
#else
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithHTML:htmlData
Copy link
Contributor

Choose a reason for hiding this comment

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

Does initWithHTML... have the same concern?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

@julianrex julianrex left a comment

Choose a reason for hiding this comment

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

Let's keep an eye on the performance changes; we may need to either move the generation of these strings earlier, consider caching - or both.

Please add a ticket for a performance test for snapshotters. 🙇

@jmkiley jmkiley merged commit d44be9a into master Nov 14, 2018
@jmkiley jmkiley deleted the jmkiley-attribution-info-string branch November 14, 2018 00:07
jmkiley added a commit that referenced this pull request Nov 14, 2018
* [ios] move creation of attributed string to global queue]

* [ios] check if on main queue
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
iOS Mapbox Maps SDK for iOS
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants