EmbeddedSources/iAsync

buildAsyncOperationWithAdapterFactoryWithDispatchQueue() crashes on cancel

Opened this issue · 3 comments

Configuration

iPad2 / iPad3 (retina)
CPU : armv7s
Configuration : Release


Completion callback executes before cancel and the object deallocates while cancel method is invoked.

1

2

3

Logs

2013-12-27 16:56:23.479 Dashboard[1227:60b] [BEGIN] buttonActionBlockCopy
2013-12-27 16:56:23.480 Dashboard[1227:60b] [BEGIN] _hud.buttonActionBlock()
2013-12-27 16:56:23.481 Dashboard[1227:60b] [unretaintedAsyncObject] respondsToSelector...
2013-12-27 16:56:23.481 Dashboard[1227:60b] selector check passed. Invoking...
2013-12-27 16:56:23.482 Dashboard[1227:60b] [BEGIN] JNUrlSessionAsyncOperation.cancel()
2013-12-27 16:56:23.483 Dashboard[1227:60b] ===[BEGIN] cancel connection
2013-12-27 16:56:23.484 Dashboard[1227:60b] ===[END] cancel connection
2013-12-27 16:56:23.485 Dashboard[1227:60b] checking self->_cancelHandler ...
2013-12-27 16:56:23.486 Dashboard[1227:60b] ===[BEGIN] invoke cancelHandler
2013-12-27 16:56:23.488 Dashboard[1227:60b] JNUrlSessionAsyncOperation.dealloc()
2013-12-27 16:56:23.491 Dashboard[1227:60b] !!!----- cookies cleared 7
2013-12-27 16:56:23.495 Dashboard[1227:60b] ===[END] invoke cancelHandler
2013-12-27 16:56:23.497 Dashboard[1227:60b] setting cancelHandler() to nil...
2013-12-27 16:56:23.498 Dashboard[1227:60b] setting connection to nil...

More logs :

2013-12-27 17:08:59.312 Dashboard[1295:60b] apiDataLoaderWithURL: ***********
2013-12-27 17:08:59.314 Dashboard[1295:60b] Completion has arrived. Disposing async object...
2013-12-27 17:08:59.315 Dashboard[1295:60b] [Done] Disposing async object...
2013-12-27 17:08:59.347 Dashboard[1295:60b] Completion has arrived. Disposing async object...
2013-12-27 17:08:59.348 Dashboard[1295:60b] [Done] Disposing async object...
2013-12-27 17:08:59.353 Dashboard[1295:60b] Completion has arrived. Disposing async object...
2013-12-27 17:08:59.354 Dashboard[1295:60b] [Done] Disposing async object...
2013-12-27 17:08:59.921 Dashboard[1295:60b] [BEGIN] buttonActionBlockCopy
2013-12-27 17:08:59.922 Dashboard[1295:60b] [BEGIN] _hud.buttonActionBlock()
2013-12-27 17:08:59.924 Dashboard[1295:60b] [unretaintedAsyncObject] respondsToSelector...
2013-12-27 17:08:59.925 Dashboard[1295:60b] selector check passed. Invoking...
2013-12-27 17:08:59.926 Dashboard[1295:60b] [BEGIN] JNUrlSessionAsyncOperation.cancel()
2013-12-27 17:08:59.926 Dashboard[1295:60b] ===[BEGIN] cancel connection
2013-12-27 17:08:59.928 Dashboard[1295:60b] ===[END] cancel connection
2013-12-27 17:08:59.929 Dashboard[1295:60b] checking self->_cancelHandler ...
2013-12-27 17:08:59.930 Dashboard[1295:60b] ===[BEGIN] invoke cancelHandler
2013-12-27 17:08:59.931 Dashboard[1295:60b] JNUrlSessionAsyncOperation.dealloc()
2013-12-27 17:08:59.932 Dashboard[1295:60b] !!!----- cookies cleared 0
2013-12-27 17:08:59.938 Dashboard[1295:60b] ===[END] invoke cancelHandler
2013-12-27 17:08:59.939 Dashboard[1295:60b] setting cancelHandler() to nil...

I believe, unretainedAsyncObject should be declared as __weak

JFFAsyncOperation buildAsyncOperationWithAdapterFactoryWithDispatchQueue(JFFAsyncOperationInstanceBuilder objectFactory,
                                                                         dispatch_queue_t callbacksQueue)
{
    objectFactory = [objectFactory copy];
    return ^JFFCancelAsyncOperation(JFFAsyncOperationProgressHandler progressCallback,
                                    JFFCancelAsyncOperationHandler cancelCallback,
                                    JFFDidFinishAsyncOperationHandler doneCallback) {

        __block id<JFFAsyncOperationInterface> asyncObject = objectFactory();

As is :

        __unsafe_unretained id<JFFAsyncOperationInterface> unretaintedAsyncObject = asyncObject;

To be :

        __weak id<JFFAsyncOperationInterface> unretaintedAsyncObject = asyncObject;