AFNetworking error 53 during attempted background fetch

◇◆丶佛笑我妖孽 提交于 2019-12-07 02:59:24

问题


While updating my application to support Background App Refresh I ran into problem with AFNetworking.

I am getting NSPOSIXErrorDomain Code=53 "Software caused connection abort". The problem seems to occur in iOS 12, where the background connection gets terminated.

AFNetworking 2.6.3 is used to make the fetch.

AppDelegate.m:

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [OrdersService performFetch];
    completionHandler(UIBackgroundFetchResultNewData);
}

OrdersService.m:

-(void) performFetch {
    [[AFHTTPRequestOperationManager new] GET:@"https://www.example.com/orders"
        parameters:nil
           success:^(AFHTTPRequestOperation *operation, id responseObject) {

           }
           failure:^(AFHTTPRequestOperation *operation, NSError *error) {

           }
    ];
}

Console output:

[Error] GET '(null)' (0) [31.9163 s]: Error Domain=NSPOSIXErrorDomain Code=53 "Software caused connection abort" UserInfo={NSErrorFailingURLStringKey=https://www.example.com/orders, _kCFStreamErrorDomainKey=1, NSErrorPeerAddressKey={length = 16, capacity = 16, bytes = 0x100201bb3e80187c0000000000000000}, _kCFStreamErrorCodeKey=53, NSErrorFailingURLKey=https://www.example.com/orders}


回答1:


Starting the fetch as background task with 0.1 sec delay solved the problem:

-(void) performFetch {
    __block UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"GET /orders" expirationHandler:^{
        // EXPIRED
        [[UIApplication sharedApplication] endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];

    // Start the long-running task and return immediately.
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Do the work associated with the task, preferably in chunks.
        [[AFHTTPRequestOperationManager new] GET:@"https://www.example.com/orders"
                        parameters:nil
                           success:^(AFHTTPRequestOperation *operation, id responseObject) {
                               // SUCCESS
                               [[UIApplication sharedApplication] endBackgroundTask:bgTask];
                               bgTask = UIBackgroundTaskInvalid;
                           }
                           failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                               // FAILURE
                               [[UIApplication sharedApplication] endBackgroundTask:bgTask];
                               bgTask = UIBackgroundTaskInvalid;
                           }
        ];
    });
}



回答2:


Some of the solutions linked below were helpful to resolve Lower protocol stack error: 53.

Informative thread on AFNetworking GitHub with relevant details and background info: AFNetworking issue

Do read the comment towards the end for insightful details:

In terms of workarounds, there’s three things you can do here, and it may make sense to do all three, or some subset, depending on the requirements of your real app. To wit:

A. If you regularly bounce in and out of your app — for example, you bounce the user out to Safari so that they can do some authentication task and then you want Safari to bounce the user back to your app — it might make sense to use a UIApplication background task to prevent your app from being suspended during those bounces.

This approach will only keep your app running for a few minutes, but if that’s sufficient for common user scenarios then it’s worthwhile doing.

B. You can retry requests yourself. Even if you weren’t running into this problem this is generally a good idea. There’s a vast array of transient issues that can cause requests to fail, and a single retry will often get you past the error without further remedial work.

The obvious gotcha here is idempotency. You can retry idempotent requests without any worries, but you’ll need some cunning app-specific logic if you want to retry non-idempotent requests.

C. You can invalidate your session when you go into the background and then re-create the session when you come back into the foreground. The new session will not share any connections with the old one, so this problem just can’t occur.

As I mentioned earlier, combining approaches might make sense. For example, A and C work together well, allowing you to avoid the cost of session invalidation unless you run out of background execution time. And you might want to do B because it has benefits outside of this problem space.

In my case, it's happening on iOS12.3 device

2019-08-05 17:38:50.988880-0700 myApp[2988:1589883] [BoringSSL] nw_protocol_boringssl_error(1584) [C15.1:4][0x10dd6e700] Lower protocol stack error: 53
2019-08-05 17:38:50.990132-0700 myApp[2988:1589883] TIC Read Status [15:0x281d59d40]: 1:53
2019-08-05 17:38:50.995585-0700 myApp[2988:1589883] Task <D62956CC-6C2B-4D5E-B1DA-0A5CA2BB60EF>.<1> HTTP load failed (error code: 53 [1:53])
2019-08-05 17:38:51.000334-0700 myApp[2988:1588479] Task <D62956CC-6C2B-4D5E-B1DA-0A5CA2BB60EF>.<1> finished with error - code: 53

Preparing your app to run in background mode: Apple's doc: How to do background fetch

Also, good source of info on background tasks: apple dev forum



来源:https://stackoverflow.com/questions/53297188/afnetworking-error-53-during-attempted-background-fetch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!