0

I use AFNetworking library to send a packetized file to the server. Every single packet is sent using separate NSURLSessionUploadTask created using AFURLSessionManager#uploadTaskWithRequest:fromData:progress:completionHandler. The number of packets differs between 1 and a couple of hundreds. Packets are sent in the order and the next won't send until the previous success.

It works just fine for most of the time but recently users (around 1% of them) started reporting that sending packets just freezes sometimes. Here is what I found in their logs:

Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=https://url.to.service/service?params=XYZ, NSErrorFailingURLKey=***, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalUploadTask <72F2E4D0-4505-4D9D-85A5-08E0DF152EE9>.<354>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalUploadTask <72F2E4D0-4505-4D9D-85A5-08E0DF152EE9>.<354>, NSLocalizedDescription=cancelled}

The app retries multiple times but recreating new NSURLSessionUploadTask and trying again, but it always fails with exactly the same error.

Here is how the code looks like (I have simplified it for the sake of readability):

@implementation PacketDataManagementService : AFHTTPSessionManager

- (void)uploadPacketData:(NSData *)packetData
{
    NSURLRequest *request = [self createRequest];

    __block NSURLSessionDataTask *task = [self uploadTaskWithRequest:request fromData:packetData progress:nil completionHandler:^(NSURLResponse *__unused response, id responseObject, NSError *error) {
      if ( error )
      {
          //log error
      }
      else
      {
          //notification to invoke `uploadPacketData` for the next packet
      }
    }];

    //adding this line was the only way to "reproduce" the issue my users have - exactly the same error is being logged
    //[task cancel];

    [task resume];
}

@end

I've tried to reproduce it without success - here is what I have tried so far:

  • users reported it on different devices and iOS versions - I didn't find any common ground here
  • AFHTTPSessionManager (PacketDataManagementService extends it) is retained between requests and stored in singleton which is used to make all those requests.
  • the request doesn't reach server - I've checked access logs of our server and requests from cancelled requests are missing.
  • I have created memory leaks to see how the app behaves close to OOM scenarios - uploads behave just fine until the app is being killed by OS.

I'm hitting a wall with my head for the last couple of days and I have no idea where else I can look at - I will appreciate any suggestions.

Krzysztof Skrzynecki
  • 2,345
  • 27
  • 39

1 Answers1

0

I have found what caused the issue - fromData: parameter in AFURLSessionManager#uploadTaskWithRequest:fromData:progress:completionHandler cannot be nil - the task is cancelled immediately when data is missing. The issue exposed the bug in another part of the app when the file I try to send is removed before.

Obviously, as soon as I figured out what was the issue I have found a similar issue reported on StackOverflow with a solution.

It's insane that Apple didn't mention this behaviour in the API documentation.

Krzysztof Skrzynecki
  • 2,345
  • 27
  • 39