-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Tests and fix for infinite loop when setting shape to nil in MGLMapViewDelegate methods #11614
Conversation
src/mbgl/map/transform.cpp
Outdated
@@ -595,12 +595,16 @@ void Transform::startTransition(const CameraOptions& camera, | |||
} | |||
observer.onCameraIsChanging(); | |||
} else { | |||
transitionFinishFn(); | |||
auto finish = transitionFinishFn; |
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.
Can you add comments explaining why this code is structured this way?
src/mbgl/map/transform.cpp
Outdated
@@ -595,12 +595,16 @@ void Transform::startTransition(const CameraOptions& camera, | |||
} | |||
observer.onCameraIsChanging(); | |||
} else { | |||
transitionFinishFn(); | |||
auto finish = transitionFinishFn; | |||
|
|||
transitionFinishFn = nullptr; | |||
|
|||
// This callback gets destroyed here, | |||
// we can only return after this point. |
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 think this comment was meant to serve as a reminder not to change this lambda such that any code executes "after this point". But this change does that. Is it safe? If so, please update this comment to explain why.
Bisecting and testing with @jmkiley's test case, it looks like this issue was introduced somewhere in: /cc @ivovandongen |
153d26e
to
3ce7934
Compare
@julianrex Looking at the test case I wonder if this is an actual bug. If the change of a source is to trigger an update of the transitions and thus callback with If the update of a source shouldn't trigger |
@jfirebaugh @ivovandongen What functionality should be disallowed in the various callbacks (e.g. onCameraDidChange)? It sounds like solution should be a two part fix:
What are you thoughts on: 1) could make it into the /cc @tobrun as this may affect Android too. |
3ce7934
to
4f973dd
Compare
Side-note: I've extracted the test changes into a new PR: #11649, and will update this PR when that has been merged. |
ddc9748
to
c75da65
Compare
c75da65
to
f5c8385
Compare
Pushed changes that I believe addresses #5833. |
5950cd2
to
0adaaba
Compare
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.
This fix deserves a blurb in the iOS and macOS changelogs.
} | ||
|
||
[NSObject cancelPreviousPerformRequestsWithTarget:expectation selector:@selector(fulfill) object:nil]; | ||
[expectation performSelector:@selector(fulfill) withObject:nil afterDelay:5.0]; |
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.
This is a lot of time to leave a test hanging. Is there any way to avoid such a long delay? If this delayed fulfillment is intended to account for rotation animation, let’s use a KVO expectation that checks whether the direction has returned to 0°.
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'm using this rather than KVO, so I can check the number of calls to this delegate method, as we were having an infinite recursion issue (and the later waitForExpectations:timeout
catches this). I do agree that the time is too long - so perhaps there's an alternative here.
src/mbgl/map/transform.cpp
Outdated
// after the temporary has been called) we stop this recursion. | ||
|
||
auto transition = transitionFrameFn; | ||
transitionFrameFn = nullptr; |
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.
Consider using std::move()
to perform this swap, as well as below when swapping with finish
.
235f24f
to
7ef5047
Compare
Rebased. |
src/mbgl/map/transform.cpp
Outdated
if (finish) { | ||
finish(); | ||
} | ||
} |
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.
Nit: }
and else if ...
on the same line.
src/mbgl/map/transform.cpp
Outdated
finish(); | ||
} | ||
} | ||
else if (!transitionFrameFn) { |
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.
Probably not -- I can imagine a situation where the camera change notification triggers the start of another transition, in which case transitionFrameFn
would be legitimately non-null.
Rebasing due to release-boba merge. |
4343bc7
to
4849c49
Compare
@julianrex I think this needs to be retargeted at |
Added failing (currently disabled) test, where the interruption still triggers an infinite loop.
4849c49
to
95b8967
Compare
Addresses #11180, #5833.
Adds integration tests and work-around to stop crash.