Why AFNetWork crashes in URLSession:dataTask:didReceiveResponse:completionHandler

168 Views Asked by At

My app crashes at line 4 in URLSession:dataTask:didReceiveResponse:completionHandler of AFURLSessionManager.m,it seems like the self object is released, the Func is where we add the callback:

- (void) Func:(AFHTTPSessionManager *)sessionManager {
    @weakify(self);
    [sessionManager setDataTaskDidReceiveResponseBlock:^NSURLSessionResponseDisposition(NSURLSession * _Nonnull session,                                                               NSURLSessionDataTask * _Nonnull dataTask, NSURLResponse * _Nonnull response) {
        @strongify(self);
        if (!self) {
            return NSURLSessionResponseCancel;
        }
      ......
     }
  ......
}

     - (void)URLSession:(NSURLSession *)session
              dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveResponse:(NSURLResponse *)response
     completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
    {
1        NSURLSessionResponseDisposition disposition = NSURLSessionResponseAllow;
2   
3       if (self.dataTaskDidReceiveResponse) {
4           disposition = self.dataTaskDidReceiveResponse(session, dataTask, response);(line 1115 of original m file)
5       }
6   
7   }

crash stack:

    Exception Type: SIGSEGV
    Exception Codes: SEGV_ACCERR at 0x58fe10485d20
    Thread 13 Crashed:
    0 libobjc.A.dylib 0x000000019d5f9c20 objc_msgSend
    1 APPInfo 0x0000000105204e0c -[AFURLSessionManager URLSession:dataTask:didReceiveResponse:completionHandler:] at AFURLSessionManager.m:1115:28
    2 CFNetwork 0x00000001a54c9934 CFURLConnectionCreateWithProperties
    3 Foundation 0x19e75f2f0 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__
    4 Foundation 0x19e7334a0 -[NSBlockOperation main]
    5 Foundation 0x19e733430 __NSOPERATION_IS_INVOKING_MAIN__
    6 Foundation 0x19e6f47d8 -[NSOperation start]
    7 Foundation 0x19e6f450c __NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__
    8 Foundation 0x19e6f9c20 __NSOQSchedule_f
    9 libdispatch.dylib 0x1ab8c1114 _dispatch_block_async_invoke2
    10 libdispatch.dylib 0x1ab8b1fdc _dispatch_client_callout
    11 libdispatch.dylib 0x1ab8b546c _dispatch_continuation_pop
    12 libdispatch.dylib 0x1ab8b4ad4 _dispatch_async_redirect_invoke
    13 libdispatch.dylib 0x1ab8c3a6c _dispatch_root_queue_drain
    14 libdispatch.dylib 0x1ab8c4284 _dispatch_worker_thread2
    15 libsystem_pthread.dylib 0x1f133bdbc _pthread_wqthread
    16 libsystem_pthread.dylib 0x1f133bb98 start_wqthread
1

There are 1 best solutions below

1
Annett Schwarze On

It may well be that the object is released, when the completion handler is invoked. To know for sure, more code snippets would be needed.

You should either check for self being nil at the beginning of the completion handler. Or you should ensure, that the reference to the instance is strongly held, so it does not get released until the completion handler is called.

One pattern to ensure, that a reference is weak until the completion handler starts and then is held on strongly while it executes is this:

__weak typeof(self) weakSelf = self;
[someObj someCall:^{
    __strong typeof(self) strongSelf = weakSelf;
    if (strongSelf == nil) return;
    ...
}];

Hope this helps.