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

Fix CustomLayer context retain count #10765

Merged
merged 2 commits into from
Dec 20, 2017
Merged

Conversation

asheemmamoowala
Copy link
Contributor

Fixes #10755

In core, with style diffing a RenderCustomLayer instance is reused if the new style has a CustomLayer with the same identifier as the previous style. This was not handled correctly in RenderCustomLayer. When the impl or context for the layer is changed, it should invoke the CustomLayerDeinitializeFunction callback.

Changes to core GL for asynchronous rendering changed when the mbgl::style::CustomLayer's CustomLayerDeinitializeFunction callback method is invoked. This resulted in the MGLOpenGLStyleLayer releasing itself early when removed from the owning style:

- (void)setStyle:(MGLStyle *)style {
if (_style && style) {
[NSException raise:@"MGLLayerReuseException"
format:@"%@ cannot be added to more than one MGLStyle at a time.", self];
}
_style.openGLLayers[self.identifier] = nil;
_style = style;
_style.openGLLayers[self.identifier] = self;

When MGLFinishCustomStyleLayer is called on a subsequent frame, it is left holding on to a dangling pointer to the layer.

To remedy this, the layer retention needs to match the lifecycle required by the async renderer. Using __bridge_retain implicitly retains the bridged pointer passed to core. This should be the correct behavior since we are not using a weak pointer. When MGLFinishCustomStyleLayer takes back ownership of the pointer from core and uses __bridge_transfer.

Apple docs for Toll-Free Bridged Types

//cc @lilykaiser @jmkiley @jfirebaugh @1ec5

@asheemmamoowala asheemmamoowala added Core The cross-platform C++ core, aka mbgl iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS labels Dec 20, 2017
Copy link
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

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

Just took a cursory glance at this PR; @akitchen, would you take a deeper look in my stead? Thanks!

@@ -77,7 +77,6 @@ @interface MGLStyle()
@property (nonatomic, readonly, weak) MGLMapView *mapView;
@property (nonatomic, readonly) mbgl::style::Style *rawStyle;
@property (readonly, copy, nullable) NSURL *URL;
@property (nonatomic, readwrite, strong) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLOpenGLStyleLayer *) *openGLLayers;
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this dictionary wound up unused after #8626. The original purpose of this dictionary was to allow -layerWithIdentifier: to return a fully initialized MGLOpenGLStyleLayer object that still had its callback implementations intact. As long as that’s still working correctly, this change looks good.

Copy link
Contributor

Choose a reason for hiding this comment

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

@1ec5 verified

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@1ec5 [MGLStlye layerFromMBGLLayer] already takes care of this for all layer types.

@1ec5 1ec5 requested a review from akitchen December 20, 2017 20:53
@akitchen
Copy link
Contributor

@1ec5 yep - darwin changes look good to me; @asheemmamoowala and I were also looking at this together yesterday. I'm currently testing with a local test case I have set up.

_style = style;
_style.openGLLayers[self.identifier] = self;
Copy link
Contributor

Choose a reason for hiding this comment

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

This is the only place where this dictionary was being used @1ec5 ; transferring the ownership is a better solution (and fixes the crash)

@akitchen
Copy link
Contributor

akitchen commented Dec 20, 2017

I'm currently testing with a local test case I have set up.

Local test case / manual verification passed. I'm toying with some automated testing strategies for this but nothing that should block the merge.

@asheemmamoowala asheemmamoowala merged commit 6a9eec8 into release-agua Dec 20, 2017
@asheemmamoowala asheemmamoowala deleted the custom-layer-fix branch December 20, 2017 22:51
@friedbunny friedbunny added this to the ios-v3.7.2 milestone Dec 20, 2017
@@ -101,7 +101,7 @@ - (instancetype)initWithIdentifier:(NSString *)identifier {
MGLPrepareCustomStyleLayer,
MGLDrawCustomStyleLayer,
MGLFinishCustomStyleLayer,
(__bridge void *)self);
(__bridge_retained void *)self);
Copy link
Contributor

Choose a reason for hiding this comment

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

It's a corner case, but: this will leak a MGLOpenGLStyleLayer that's init'd but never added to a map.

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 knew I was missing something! Moved to : #10771

akitchen pushed a commit that referenced this pull request Jan 5, 2018
Revert this commit to see integration test fail.
akitchen pushed a commit that referenced this pull request Jan 8, 2018
Revert this commit to see integration test fail.
akitchen pushed a commit that referenced this pull request Jan 9, 2018
Revert this commit to see integration test fail.
akitchen pushed a commit that referenced this pull request Jan 12, 2018
Revert this commit to see integration test fail.
akitchen pushed a commit that referenced this pull request Jan 19, 2018
Revert this commit to see integration test fail.
akitchen pushed a commit that referenced this pull request Jan 20, 2018
Revert this commit to see integration test fail.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Core The cross-platform C++ core, aka mbgl iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants