Afnetworking: [iOS 12 Beta 11] NSPOSIXErrorDomain Code=53: Software caused connection abort

Created on 30 Aug 2018  Ā·  78Comments  Ā·  Source: AFNetworking/AFNetworking

I'm experiencing this issue in iOS 12 Beta 11 using last version of the framework (3.2.1).
The complete error localised description is:

HTTP load failed (error code: 53 [1:53])
2018-08-30 11:54:43.390749+0200 Background[2224:809685] Task <7CD7B0DD-2CE2-400D-AC02-D66C0F4E4847>.<7> finished with error - code: 53
2018-08-30 11:54:43.391271+0200 Background[2224:809125] Task <7CD7B0DD-2CE2-400D-AC02-D66C0F4E4847>.<7> load failed with error Error Domain=NSPOSIXErrorDomain Code=53 "Software caused connection abort" UserInfo={_NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <7CD7B0DD-2CE2-400D-AC02-D66C0F4E4847>.<7>, _kCFStreamErrorDomainKey=1, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <7CD7B0DD-2CE2-400D-AC02-D66C0F4E4847>.<7>"
), _kCFStreamErrorCodeKey=53} [53]
failure The operation couldn’t be completed. Software caused connection abort

The bug is easy to reproduce: you have just to put the application in background, wait for few seconds and restore it to foreground state.

I've reproduced it in a blank application, that I'm attaching there.

Feel free to ask if you have any doubts :)
Giovanni
Background.zip

stale

Most helpful comment

I was also struggling with this problem, so I submitted a Technical Support Incident. I spoke with an Apple engineer and I want to share some of the insights he provided me. In my case, requests were aborted shortly after the app returned from the background. A reproduction scenario for my specific case can be found here https://github.com/jaapmengers/abortedrequestsreproduction

So, requests are aborted when the app moves to the background through a process called socket resource reclaim. It closes the TCP connection out from underneath the socket being used to run your requests. More information about that process can be found here https://developer.apple.com/library/archive/technotes/tn2277/_index.html

In iOS 11.4 and iOS 12 there's been changes in the way socket resource reclaim is applied. To quote the engineer I spoke to:

Historically, the system was quite conservative about socket resource reclaim. The best way to trigger it was to screen lock the device.

At some point during the iOS 11.x cycle we made the system much more aggressive about this. Socket resource reclaim is now run whenever the app is suspended. This isn’t considered a regression because we never documented the exact circumstances under which socket resource reclaim would run. When I wrote TN2277 I was deliberately circumspect about this, saying only:

The exact circumstances under which the system might reclaim a
socket's resources are purposely not documented; this gives us
flexibility to improve things in the future.

There are two standard solutions to this problem:

  • If you expect the user to come back to your app promptly, you can use a UIApplication background task to prevent the app from being suspended while it’s in the background. Socket resource reclaim can only happen while your app is suspended, and the presence of the UIApplication background task prevents that.

Note: For some hints and tips on how to use UIApplication background tasks effectively, see my "UIApplication Background Task Notes" post on DevForums: https://forums.developer.apple.com/message/253232#253232

  • For requests that you want to continue no matter how long your app is suspended, you can run the request in an URLSession background session.

However, my issue was with socket resource reclaim closing connections for requests that I triggered _after_ my app returned from the background. When I asked him about this, he gave me some background on how URLSession works.

When your app issues a request, URLSession starts a TCP connection over which to run the this request. When the request completes URLSession holds on to this TCP connection in case you issue a new request. In HTTP 1.1 this connection caching is a very common performance optimization. In HTTP/2 it’s a standard part of the protocol. When the user moves your app to the background, the system suspends your app and then reclaims socket resources.
When the user then moves the app back to the foreground and your app issues a new request, URLSession assigns this request to one of its cached connections, at which point it notices the socket resource reclaim and fails the request.

Now it get's interesting:

Normally I'd expect URLSession to automatically retry the request in this case. However, there are some circumstances under which this retry is impossible. Specifically, URLSession will never retry a non-idempotent request because it can’t be sure whether bits of the request made it to the server or not.

Note: This concept is explained in more detail in QA1941 "Handling "The network connection was lost" Errors": https://developer.apple.com/library/archive/qa/qa1941/_index.html

In my example project, the request is in fact idempotent. We use an HTTP GET which according to the documentation should be eligible for retry.

This seems to in fact be a bug. Quote:

Digging into this further I think I know what’s going on here. In recent OS releases there’s been a change in how URLSession manages the TCP connections that underlying its HTTP[S] connections, moving from an older system built in to URLSession; to a new system based on the Network framework. I believe that's preventing the idempotent retry in this case. The retry is keyed of specific errors, and the error coming up from the Network framework in this case (53, or ECONNABORTED) does not match those expectations.

Having established that this is a bug (and having submitted it as such), I asked about some workarounds:

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.

I'm now in the process of evaluating the workarounds and seeing what best works for my situation.
I hope this helps you all.

All 78 comments

Note: to reproduce it you have to use a real device. I've never reproduced it into simulator

Nevermind for it, it seems to be an apple bug, because I've reproduced it also using URLSessionManager methods.

I've opened a new bug here, if interested -> https://bugreport.apple.com/web/?problemID=43882930

@Gioevi90 Same problem with you. Got any reply from apple?

@soulmercy
they said that my bug is a duplicated of another already opened bug, and that for privacy I can't have access to that.
They also said that I have visibility of the state in bug report. At the moment, the bug is still on open status. :(

Thanks for reporting! We'll leave this open for now so people Googling the problem can find it more easily.

@Gioevi90 can you share the link of the already reported bug, so that we can also have a visibility of the state in bug report.

@siddharthsuneel The link it's the same I've posted at the start of the discussion :) https://bugreport.apple.com/web/?problemID=43882930

let me know if you're able to see that :) (I've got some doubt, because it is related to my apple developer account, so for privacy concerns I think you won't be able to see that)

G.

@Gioevi90 Other people won’t be able to see that link; people use Open Radar to get around that problem.

@Gioevi90 Are you seeing this on the Xcode 10 GM?

I am using Xcode 10 GM and am able to reproduce the bug with the code you provided. Since there is not a solution yet I looking for work-arounds. Wrapping your get call inside a dispatch async after seems to prevent the issue. This only seems to work with a delay ... if you remove it then the error still occurs. Let me know what you think.

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {

        self.sessionManager?.get("https://reqres.in/api/users", parameters: nil, progress: nil, success: { (task, data) in
            print("success")
        }, failure: { (task, error) in
            print("failure \(error.localizedDescription)")
        })

    }

Any luck finding a solution for this?
I have the same problem when using Alamofire. Also only happens on device and not simulator.
Wondering if this is an iOS 12 bug, or AFNetworking/Alamofire issue?

I am using Xcode 10 GM and am able to reproduce the bug with the code you provided. Since there is not a solution yet I looking for work-arounds. Wrapping your get call inside a dispatch async after seems to prevent the issue. This only seems to work with a delay ... if you remove it then the error still occurs. Let me know what you think.

  DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {

      self.sessionManager?.get("https://reqres.in/api/users", parameters: nil, progress: nil, success: { (task, data) in
          print("success")
      }, failure: { (task, error) in
          print("failure \(error.localizedDescription)")
      })

  }

This workaround doesn't seem to work for me.

Domain=NSPOSIXErrorDomain Code=53 "Software caused connection abort"

I didn't use AFNetworking, but I reproduce same error code.

That Error occurred when attempting network communication at the timing of UIApplication.willEnterForegroundNotification.
I changed the timing to UIApplication.didBecomeActiveNotification, the problem no longer occurs.

I do not know it will be helpful, but I hope it will fix :)

Domain=NSPOSIXErrorDomain Code=53 "Software caused connection abort"

I didn't use AFNetworking, but I reproduce same error code.

That Error occurred when attempting network communication at the timing of UIApplication.willEnterForegroundNotification.
I changed the timing to UIApplication.didBecomeActiveNotification, the problem no longer occurs.

I do not know it will be helpful, but I hope it will fix :)

Appreciate your help. In my case I have network calls while polling an endpoint that returns Okta MFA approval status. If the user briefly puts the app into background to respond to the Okta prompt from the Okta app, the url request gets cancelled with the error 53 above.
I noticed the same is true for any url request that does not complete while the app is active.
And this used to work fine with iOS 11 and 10 and built with Xcode 9.

So I ended up having to increase the delay time to .3 seconds. Maybe try that?

On Sep 21, 2018, at 7:24 PM, Gabor Sajo <[email protected]notifications@github.com> wrote:

I am using Xcode 10 GM and am able to reproduce the bug with the code you provided. Since there is not a solution yet I looking for work-arounds. Wrapping your get call inside a dispatch async after seems to prevent the issue.. This only seems to work with a delay ... if you remove it then the error still occurs. Let me know what you think.

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {

            self.sessionManager?.get("https://reqres.in/api/users", parameters: nil, progress: nil, success: { (task, data) in
                    print("success")
            }, failure: { (task, error) in
                    print("failure \(error.localizedDescription)")
            })

    }

This workaround doesn't seem to work for me.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHubhttps://github.com/AFNetworking/AFNetworking/issues/4279#issuecomment-423702219, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AHQP_Yt15308eK1IbA3B8jbnSJU1LE4Rks5udYMRgaJpZM4WTO4P.


This email and any files transmitted with it are confidential and are intended solely for the use of the individual or entity to whom they are addressed. If you are not the intended recipient, you are notified that disclosing, copying, distributing or taking any action in reliance upon the contents of this message is strictly prohibited. Additionally, we kindly request that, if delivered to you in error, you please notify the sender immediately by email and that you delete this message and any accompanying files permanently from your system.

Here is a simple test that demonstrates the problem.
When you run the test app with this view controller then immediately swipe to the phone home screen the data request is cancelled with error 53.

`class ViewController: UIViewController
{
let defaultSession = URLSession(configuration: .default)
var dataTask: URLSessionDataTask?

override func viewDidLoad()
{
    super.viewDidLoad()
    self.run()
}

func run()
{
    guard let url = URL(string: "https://httpbin.org/delay/5") else { return }
    print(url.absoluteString)

    self.dataTask = defaultSession.dataTask(with: url)
    {
        data, response, error in

        defer { self.dataTask = nil }

        if let error = error
        {
            print(error.localizedDescription)
        }
        else if let data = data,
            let response = response as? HTTPURLResponse,
            response.statusCode == 200
        {
            print("\(data.count) bytes received")
        }
    }
    dataTask?.resume()
}

}

`

Thanks to all guys :)

I've received yesterday communications Apple side: they said that they are still investigating on the problem... the bug is apple side and they don't know when the issue will be solved.

By the way, I don't think that I can use any of the workarounds described here in my project.
I'm waiting for a solution apple side then ;)
I will update you as soon as possible when I'll have communications apple side :)

Thanks

Yeah this is a very serious bug IMHO.
Basically you cannot expect a network call to ever complete if the app os not in foreground.
Using background session configuration also fails BTW.

Seeing the same thing. @Gioevi90 please keep us updated.

The great guys from Alamofire suggested to use background tasks for network calls that may need to complete if the app is backgrounded.
I updated my code to do that on potentially long running tasks and it works well.

https://forums.developer.apple.com/thread/85066

What happens on iOS 11 and earlier? iOS is still going to suspend the threads for the app unless a background task or download is started, so if a request is pending it can still end up timing out or aborting when the app is eventually foregrounded again.

Relying to myself, I guess iOS 12 is more aggressively killing active connections/sockets even for very brief periods of suspending. https://developer.apple.com/library/archive/technotes/tn2277/_index.html (quite an old doc now) describes how sockets can survive backgrounding and suspending, but it seems something has changed here.

Wrapping all requests in background tasks resolved the issue for me as well. I would still consider this a consider this a critical bug since Apple never provided any warning about this change in iOS 12.

So would it be possible for you to include some example code of how you wrapped the request in a background task. I can’t seem to do it right.

On Oct 5, 2018, at 10:11 AM, Jim Howell <[email protected]notifications@github.com> wrote:

Wrapping all requests in background tasks resolved the issue for me as well. I would still consider this a consider this a critical bug since Apple never provided any warning about this change in iOS 12.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHubhttps://github.com/AFNetworking/AFNetworking/issues/4279#issuecomment-427398782, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AHQP_QsNe4i69ncQvfJpQFtc4NcJPTthks5uh3augaJpZM4WTO4P.


This email and any files transmitted with it are confidential and are intended solely for the use of the individual or entity to whom they are addressed. If you are not the intended recipient, you are notified that disclosing, copying, distributing or taking any action in reliance upon the contents of this message is strictly prohibited. Additionally, we kindly request that, if delivered to you in error, you please notify the sender immediately by email and that you delete this message and any accompanying files permanently from your system.

With Alamofire it's very easy to also add a retry logic in case of this error.

here's the apple developer page on background execution:

https://developer.apple.com/library/archive/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

So I just put this before every request is sent:

bgTask = [application beginBackgroundTaskWithName:nil expirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];

And I put this in the completion block when every request returns:

[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;

Now requests finish when the app is moved to the background.

Thanks

On Oct 8, 2018, at 8:24 AM, Jim Howell <[email protected]notifications@github.com> wrote:

here's the apple developer page on background execution:

https://developer.apple.com/library/archive/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

So I just put

bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{

// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];

Before every request is sent. And I put:

```

[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;

Just inside the completion block when a request returns. Now requests finish when the app is moved to the background.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHubhttps://github.com/AFNetworking/AFNetworking/issues/4279#issuecomment-427830725, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AHQP_RoMFvk6v8atV06eqvZ9V1_UjKkvks5ui1IbgaJpZM4WTO4P.


This email and any files transmitted with it are confidential and are intended solely for the use of the individual or entity to whom they are addressed. If you are not the intended recipient, you are notified that disclosing, copying, distributing or taking any action in reliance upon the contents of this message is strictly prohibited. Additionally, we kindly request that, if delivered to you in error, you please notify the sender immediately by email and that you delete this message and any accompanying files permanently from your system.

I seem to be getting the same problem. Just to clarify, I'm not talking about ongoing requests being cancelled when the app goes into the background. I'm referring to requests being cancelled (or not even tried?) when performed too early, before the app enters the foreground. In OP's case in applicationWillEnterForeground, and in my case when handling deep links in the application delegate (Facebook Login callback or my own deep links).
Both problems described here might have the same root cause, but the flow is slightly different. šŸ˜‰

Retry failed requests seem works for me. I'm using Alamofire and it supports RequestRetrier to retry any requests before it really returns the error.

I get same problem using NSURLSession directly from within applicationWillEnterForeground. Just in case this helps anyone, I found a simple workaround: prior to making any network calls from within applicationWillEnterForeground, discard and recreate your NSURLSession. Of course this will cause network connections to be recreated but I prefer it to using a delay-based solution that may behave differently on different devices.

I get this error too when I try to login with facebook sdk which takes me to the facebook app and then back and in the closure I make a call to my server to login with the facebook user.

I fixed temporarily by adding a 1s delay before calling my server to give the switch app animation time to complete which makes my app become active I assume.

@Gioevi90 bug report is not available anymore, can you let us know what was the conclusion on the issue?

Is it possible to have this background task wrapper in AFNetworking? It may be a parameter or by default?

Is it possible to have this background task wrapper in AFNetworking? It may be a parameter or by default?

I think I remember hearing that creating too many BG tasks can cause problems, and depending on the rate of requests it might be a bad default to automatically wrap every request in a BG task. I don't remember the source of that, and I don't know how many is "too many", so I realize this not a particularly helpful comment.

Yeah the begin background task requires a UIApplication instance to be present, which may not be always practical. So wrapping every AF request is not a good approach IMHO.

@Gioevi90 Did you get any update from apple on this ? Ofcourse adding the delay fixed my issue.
Thanks.

Wow glad I found this, this is super frustrating. Wrapping every call in a background task feels super dirty. Hopefully there's a cleaner resolution soon.

Hi guys,
unfortunately I've no updates apple side. At the moment the bug is still duplicated and open. I've tried to ask for more informations in the thread, but I received a pre-compilated response saying that the bug is still open and that they're still investigating on that.

Unrelated to this framework, but is this the same issue with safari (or chrome) killing ongoing ajax connections when the browser is put in the background? I noticed that simply hitting the home button, or even opening the camera or file library for a file upload causes this

This post on the developer forums about background tasks and gives a lot more information about how they work:

https://forums.developer.apple.com/thread/85066

I think I remember hearing that creating too many BG tasks can cause problems, and depending on the rate of requests it might be a bad default to automatically wrap every request in a BG task. I don't remember the source of that, and I don't know how many is "too many", so I realize this not a particularly helpful comment.

According to the post, iOS 11 introduced a hard limit of 1000 background tasks, so as long as you're well below that you're fine. Also, the "beginBackgroundTaskWithExpirationHandler" doesn't actually start a background task unless the app is moved to the background while the request is being made, so it's a misleading function name.

Yeah the begin background task requires a UIApplication instance to be present, which may not be always practical. So wrapping every AF request is not a good approach IMHO.

I'm not really sure how this would be an issue since UIApplication is a singleton that's always available. I agree that it feels hacky though.

Unrelated to this framework, but is this the same issue with safari (or chrome) killing ongoing ajax connections when the browser is put in the background? I noticed that simply hitting the home button, or even opening the camera or file library for a file upload causes this.

lol that could definitely be the case. I don't understand how Apple hasn't fixed this yet if it's an issue with Chrome and Safari.

iOS12 has extra applicationWillResignActive event. So If when want to fix this bug. We should add retry by Check error code 53 or application state.

After I locked my iPhone's screen, open app by push event. log is:

//iOS11.4.1

2018/11/30 16:06:46 AppDelegate -[AppDelegate applicationWillEnterForeground:] XX: apns push:

2018/11/30 16:06:46 APNSManager -[APNSManager userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:] XX: apns push

2018/11/30 16:06:46 AppDelegate -[AppDelegate applicationDidBecomeActive:] XX: apns push:

​
//iOS12.1

2018/11/30 16:13:25 AppDelegate -[AppDelegate applicationWillEnterForeground:] XX: apns push:

2018/11/30 16:13:25 APNSManager -[APNSManager userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:] XX: apns push

2018/11/30 16:13:25 AppDelegate -[AppDelegate applicationDidBecomeActive:] XX: apns push:

2018/11/30 16:13:25 AppDelegate -[AppDelegate applicationWillResignActive:] XX: apns push:

2018/11/30 16:13:26 AppDelegate -[AppDelegate applicationDidBecomeActive:] XX: apns push:

I was also struggling with this problem, so I submitted a Technical Support Incident. I spoke with an Apple engineer and I want to share some of the insights he provided me. In my case, requests were aborted shortly after the app returned from the background. A reproduction scenario for my specific case can be found here https://github.com/jaapmengers/abortedrequestsreproduction

So, requests are aborted when the app moves to the background through a process called socket resource reclaim. It closes the TCP connection out from underneath the socket being used to run your requests. More information about that process can be found here https://developer.apple.com/library/archive/technotes/tn2277/_index.html

In iOS 11.4 and iOS 12 there's been changes in the way socket resource reclaim is applied. To quote the engineer I spoke to:

Historically, the system was quite conservative about socket resource reclaim. The best way to trigger it was to screen lock the device.

At some point during the iOS 11.x cycle we made the system much more aggressive about this. Socket resource reclaim is now run whenever the app is suspended. This isn’t considered a regression because we never documented the exact circumstances under which socket resource reclaim would run. When I wrote TN2277 I was deliberately circumspect about this, saying only:

The exact circumstances under which the system might reclaim a
socket's resources are purposely not documented; this gives us
flexibility to improve things in the future.

There are two standard solutions to this problem:

  • If you expect the user to come back to your app promptly, you can use a UIApplication background task to prevent the app from being suspended while it’s in the background. Socket resource reclaim can only happen while your app is suspended, and the presence of the UIApplication background task prevents that.

Note: For some hints and tips on how to use UIApplication background tasks effectively, see my "UIApplication Background Task Notes" post on DevForums: https://forums.developer.apple.com/message/253232#253232

  • For requests that you want to continue no matter how long your app is suspended, you can run the request in an URLSession background session.

However, my issue was with socket resource reclaim closing connections for requests that I triggered _after_ my app returned from the background. When I asked him about this, he gave me some background on how URLSession works.

When your app issues a request, URLSession starts a TCP connection over which to run the this request. When the request completes URLSession holds on to this TCP connection in case you issue a new request. In HTTP 1.1 this connection caching is a very common performance optimization. In HTTP/2 it’s a standard part of the protocol. When the user moves your app to the background, the system suspends your app and then reclaims socket resources.
When the user then moves the app back to the foreground and your app issues a new request, URLSession assigns this request to one of its cached connections, at which point it notices the socket resource reclaim and fails the request.

Now it get's interesting:

Normally I'd expect URLSession to automatically retry the request in this case. However, there are some circumstances under which this retry is impossible. Specifically, URLSession will never retry a non-idempotent request because it can’t be sure whether bits of the request made it to the server or not.

Note: This concept is explained in more detail in QA1941 "Handling "The network connection was lost" Errors": https://developer.apple.com/library/archive/qa/qa1941/_index.html

In my example project, the request is in fact idempotent. We use an HTTP GET which according to the documentation should be eligible for retry.

This seems to in fact be a bug. Quote:

Digging into this further I think I know what’s going on here. In recent OS releases there’s been a change in how URLSession manages the TCP connections that underlying its HTTP[S] connections, moving from an older system built in to URLSession; to a new system based on the Network framework. I believe that's preventing the idempotent retry in this case. The retry is keyed of specific errors, and the error coming up from the Network framework in this case (53, or ECONNABORTED) does not match those expectations.

Having established that this is a bug (and having submitted it as such), I asked about some workarounds:

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.

I'm now in the process of evaluating the workarounds and seeing what best works for my situation.
I hope this helps you all.

I already imlemented method A only and no more problems so far šŸ‘

@jaapmengers Thanks for sharing. It is super helpful. So given that the idempotent retries is a bug, is there any existing bug file for this? I had to implement my own retries to all of my GET requests. Now I need to figure out the none idempotent which I'm thinking to probably wrap on a BG task.

It's quite disappointing that we have to reach to this level to get the answers of why these are happening.

I found this because I used a shared session manager, but it's not valid when application will enter foreground.
So I create a new session manager when application will enter foreground, this error disappear.

@Grayon Yes. It's because the socket that you had on your shared session manager has not yet been re-assigned to it on enterforeground. Another workaround is to add delay on enterforeground before you use your shared session manager

@teffi Do you mean using URLSession.shared here and adding a delay on what I do in func applicationWillEnterForeground(_ application: UIApplication)? Can you tell me how big the delay should be?

@kmaschke85 Yes. Add the delay before you call send your request. In my case 0.7s but according to @arbitur 1s works for him.

I resolved this issue adding RequestRetrier to my requests and adding a 0.7s delay.

Hey all, I was just notified by Apple that this issue has been closed! The original issue # they give is 42287299. There doesn't seem to be any indication of when the fix will be released, but I'm hoping it is in the next version of iOS.

@ianlovejoy Nice! Could you share the radar issue link?

Hey all, I was just notified by Apple that this issue has been closed! The original issue # they give is 42287299. There doesn't seem to be any indication of when the fix will be released, but I'm hoping it is in the next version of iOS.

So was I! I really hope that it has been closed with resolved status (the only thing we know at the moment is that it has been closed).

Cross fingers :)

I asked for a time frame for release and received the following from Apple:

Although the original report on this issue, Bug ID XXXXX, is closed, a solution will not be available externally for some time. We cannot provide any specific timetable, but we suggest testing with the next major release when available for beta tests. If you still see the issue in that or a newer release, please file a new bug report.

By "major release" I assume they mean iOS 13. :(

@teffi I wish I could share the link, but it seems to be only accessible to me.

mark

Issue is been resolved or not any update.Apple released 12.2 version also but still issue is there.Any one have idea how to deal with this

We'll likely have to wait until iOS 13, sadly.

12.1.2 the problem has arisen,
stay concerned

is there any workaround for this? sessions that are also set up as "background" getting cancelled.

Hi guys, replicating this for a request fired while an app is going background is quite easy, but is anyone able to reliably reproduce this for a request when the app is going foreground?

@petrpavlik I can reproduce it if I start a webservice request when the app is in background and bounce to foreground from an universal link.

 func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
 //make a webservice call here, it will return the error
}

This isn’t considered a regression because we never documented the exact circumstances under which socket resource reclaim would run. ... This gives us flexibility to improve things in the future.

I love that. As long as you don't explicitly document how a feature should work, you can break it and it's not a bug. And this even seems to apply if the feature in question is something that almost all of the developers on your platform have used in the same way for years.

I'll be sure to remember that little pearl of wisdom next time a client complains that something isn't working. "Oh, we never actually documented that it would work so this is your problem, not ours".

I'm using Moya/Alamofire to fetch the server data when a push notification arrives (application:didReceiveRemoteNotification:). Sometimes the error code is ECONNABORTED which I can use to retry a request. Sometimes the error code is not set which is bad.
Hacking and waiting for iOS13...

Has anyone checked if this went away with iOS 13 now that the developer beta is out?

I have tested this issue in iOS 13 beta but still connection get aborted by OS once I press the iOS device home button to send the app in background
I don't know ,why apple not taking this issue seriously
If any one have any alternative solution for this ,Please help me

@bandanagaur the alternative solutions are all listed above. Choose from whichever one suits your case.

@g4r37h what are the alternative solutions? i am scheduling background downloads. these are getting cancelled by the OS when going to the background (although i configure it to be a background session).

What else can i do to overcome this problem ?

I seem to be getting the same problem. Just to clarify, I'm not talking about ongoing requests being cancelled when the app goes into the background. I'm referring to requests being cancelled (or not even tried?) when performed too early, before the app enters the foreground. In OP's case in applicationWillEnterForeground, and in my case when handling deep links in the application delegate (Facebook Login callback or my own deep links).
Both problems described here might have the same root cause, but the flow is slightly different. šŸ˜‰

I have the same problem with deep link and a Xamarin iOS app. We make a REST call soon after the app public override bool ContinueUserActivity has been called by the third party service. The call works most of the times. Unfortunately, on occasions, we get:

DEBUG The server could not be reached: System.Net.WebException: The network connection was lost. ---> Foundation.NSErrorException: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x2806f7e70 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=.<70>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <00976193-602E-4C95-AA15-92AF8B5482E3>.<70>"
), NSLocalizedDescription=The network connection was lost.,

I found a way work for me, for reference only.
In AppDelegate, add

var backgroundTask: UIBackgroundTaskIdentifier = .invalid

func applicationWillResignActive(_ application: UIApplication) {
        backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in
            self?.endBackgroundTask()
        }
  }

func endBackgroundTask() {
        print("Background task ended.")
        UIApplication.shared.endBackgroundTask(backgroundTask)
        backgroundTask = .invalid
    }

I catch the same error on my iPhoneX with iOS 12.2 And I am looking for appropriate solutions, thanks for help.

    "_NSURLErrorFailingURLSessionTaskErrorKey" = "LocalDataTask <98135840-ECC6-4CEF-A2C2-CD677703167A>.<1>";
    "_NSURLErrorRelatedURLSessionTaskErrorKey" =     (
        "LocalDataTask <98135840-ECC6-4CEF-A2C2-CD677703167A>.<1>"
    );
    "_kCFStreamErrorCodeKey" = 53;
    "_kCFStreamErrorDomainKey" = 1;

I refer to Faydee1220's code resolved my problem:

@interface AppDelegate ()
@property (nonatomic, assign) UIBackgroundTaskIdentifier taskIdentifier;
@end

@implementation AppDelegate
- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    if (self.taskIdentifier != UIBackgroundTaskInvalid) {
        [application endBackgroundTask:self.taskIdentifier];
        self.taskIdentifier = UIBackgroundTaskInvalid;
    }

    __weak typeof(self) weakSelf = self;
    self.taskIdentifier = [application beginBackgroundTaskWithName:nil expirationHandler:^{
        [application endBackgroundTask:weakSelf.taskIdentifier];
        weakSelf.taskIdentifier = UIBackgroundTaskInvalid;
    }];

}

@end

Are you guys still able to reproduce the problem with the sample project provided by @Gioevi90 ?
I could not reproduce it using iOS 12.3.1 - iPhone 6S.

Are you guys still able to reproduce the problem with the sample project provided by @Gioevi90 ?
I could not reproduce it using iOS 12.3.1 - iPhone 6S.

I caught the same problem on my iPhone 6S - iOS 12.3.1, It is a small probability happening in my project. Hope to help you.

I can reproduce this on Safari 12.1.2 iOS 12.4 :(

I'm reproducing this on iOS 12.4.4.

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

This issue has been auto-closed because there hasn't been any activity for at least 21 days. However, we really appreciate your contribution, so thank you for that! šŸ™ Also, feel free to open a new issue if you still experience this problem šŸ‘.

I can still reproduce this issue on iOS 13.3.1 :(

can still reproduce this issue on iOS 13.4.1

Might have something to do with https://stackoverflow.com/a/25996971/2258249

Was this page helpful?
0 / 5 - 0 ratings