I was exploring the scenarios where an NWListener or NWConnection can be invalidated or reclaimed by the OS itself.
I came across the document TN2277: Networking and Multitasking, which discusses situations where iOS can reclaim the underlying socket descriptor.
The document states:
while the app is suspended the system may choose to reclaim resources out from underneath a network socket used by the app, thereby closing the network connection represented by that socket.
From this, I understand that when the app is in a suspended state, the OS may reclaim the socket descriptor.
My questions are:
- In what scenarios does the OS not reclaim the socket descriptor while the app is suspended, and in which cases does it reclaim it?
- When reclamation occurs, does the OS reclaim 'a' single NWListener/NWConnection, or does it reclaim 'all' NWListener/NWConnections opened by the application?
Thanks.
First up, TN2277 hasn’t been updated in years so, while the gist of the technote is still correct, a number of details have drifted:
- Network framework generally doesn’t use BSD Sockets under the covers, but rather the user-space networking stack.
- Given that, the term socket resource reclaim no longer makes a lot of sense. These days I simply say that the connection or listener was defuncted [1].
1- In what scenarios does the OS the socket descriptor while the app is … ?
This is an implementation detail, and the behaviour has changed over time. Historically iOS would delay the defunct until you screen lock the device. Hence the advice in the Testing Socket Reclaim section of TN2277.
However, that changed years ago. Nowadays iOS will defunct things as soon as the app gets suspended.
2- When reclamation occurs, does the OS reclaim single NWListener/NWConnection … ?
Again, that’s an implementation detail, but my experience is that it defuncts all network connections and listeners.
In this post I’ve talked a lot about implementation details. That’s useful, because it help you understand observed behaviour, but you have to be careful not to encode that knowledge into your product. The high-level advice in TN2277 still stands:
- When your app becomes eligible for suspension, stop any listeners.
- For network connections, think carefully about whether it’s reasonable for this connection to just go deaf when your app gets suspended.
- If not, close it when your app becomes eligible for suspension.
- In all cases, check for and handle errors so that, if your listener or connection gets defuncted, you behave in a reasonable fashion.
Oh, and there’s one last point I should add:
- Test this stuff outside of Xcode. Xcode’s debugger prevents your app from being suspended, so you can’t reliable test background behaviour from Xcode. See Testing and Debugging Code Running in the Background for more advice on this.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] Which is a term I picked up from the networking stack.