ashare80 / TSClusterMapView

MKMapView with animated clustering for iOS and OSX
MIT License
149 stars 21 forks source link

Random Crash in initAnnotationsPool method of TSClusterMapView #5

Closed yorgosg closed 8 years ago

yorgosg commented 9 years ago

I have noticed a crash that happens rarely. The crash happens in the alloc init of the ADClusterAnnotation, in the initAnnotationPools.

appname(46839,0x10a642310) malloc: * error for object 0x7ffa01ae89b8: incorrect checksum for freed object - object was probably modified after being freed. * set a breakpoint in malloc_error_break to debug

ashare80 commented 9 years ago

Hmm maybe there's a race condition that's causing the loop to be run more than once. I'll look into it.

If you can recreate the bug, could you check to see which object is causing the problem from the memory location (0x7ffa01ae89b8) in the debugger?

yorgosg commented 9 years ago

will do, thanks!

On Feb 11, 2015, at 01:02 , Adam Share notifications@github.com wrote:

Hmm maybe there's a race condition that's causing the loop to be run more than once. I'll look into it.

If you can recreate the bug, could you check to see which object is causing the problem from the memory location (0x7ffa01ae89b8) in the debugger?

— Reply to this email directly or view it on GitHub.

jpmhouston commented 9 years ago

I've also seen crashes in initAnnotationPools: when running in the simulator, this is one of them I've seen a few times, when called from mapView:regionDidChangeAnimated::

if (!_clusterAnnotationsPool) {
    _clusterAnnotationsPool = [[NSMutableSet alloc] initWithCapacity:numberOfAnnotationsInPool];
    for (int i = 0; i < numberOfAnnotationsInPool; i++) {
        ADClusterAnnotation * annotation = [[ADClusterAnnotation alloc] init];
        [_clusterAnnotationsPool addObject:annotation];
    }

    toAdd = _clusterAnnotationsPool.allObjects;  <----- here
}

The message printed to the lldb console: Description of exception being thrown: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[450]' Warning: hit breakpoint while running function, skipping commands and conditions to prevent recursion.

And interestingly, while 180 is passed in and numberOfAnnotationsInPool is 360, clusterAnnotationsPool has 617 objects. Printing this object in lldb at this point shows 556 ADClusterAnnotation objects and 61 "(null)"! Could it be multiple threads trying to modify clusterAnnotationsPool and corrupting it? [Answer: YES!! see the Edit at the end]

At the time of this crashed on the main thread, another thread was running the tree building queue and seems to be starting TSClusterOperations, I don't happen to see anything that touches clusterAnnotationsPool.

Edit: I just saw a different crash, and both the main thread and the tree building queue were both in initAnnotationPools:! So yes, I'd guess that these crashes are all because clusterAnnotationsPool gets modified by multiple threads simultaneously. Should locks or similar mechanism be added to prevent this, at what level of granularity? Or is a minor redesign warranted to adjust what's done in background threads? For now, I'm deferring my call to setRegion:animated: on the main thread to hopefully avoid this (deferring it until the first call to mapViewDidFinishRenderingMap: having the effect of rendering the world map then zooming in)

ashare80 commented 9 years ago

@jpmhouston thanks for pointing this out. I'll try to get out a fix asap

ashare80 commented 9 years ago

@jpmhouston Just pushed new version see if that resolves the issue