Is there any Apple documentation or any developer experience to help me understand why a listening TCP server socket on iOS device might become broken after long app inactivity and how to detect the case and restore the socket?
The long story:
My app has two components that mostly communicate with each other over TCP with address 127.0.0.1, that is, localhost.
The connection is not open all the time, it gets open only on demand in specific situations, when the client component connects to the other side on localhost or some other service on the Internet.
Localhost server is running all the time without restarts to be always ready to accept connections when needed.
In general, everything works fine and stable for hours of testing.
But when the app has been left idle for some time (10 minutes) and I wake it up to test, my blocking accept()on the server socket starts always failing with ECONNABORTED (errno code 53, message Software caused connection abort), and connect() call (which is non-blocking on the client side and is waiting with select() for state changes) almost immediately returns an error ECONNREFUSED (code 61, message Connection refused) when I retrieve current state with getsockopt
It just makes no sense because
- the server socket on the same device should be listening on 127.0.0.1 all the time. My code did never call close() on the socket nor unbind or break it in any other way. There are no other errors that might suggest the server socket is not bound or not listening anymore. Still, the connecting side always fails with ECONNREFUSED.
- my accept() code is blocking - it waits for connections, while I run the connect() code in a loop with 10 second waiting in between. Clearly, at least one of those connection attempts should succeed, but they do not. The accept() call seems to be blocking as it should - it waits until the connect() code is executed on the client side and only then almost immediately fails with ECONNABORTED (while connect() fails with ECONNREFUSED at the same moment).
Why a valid listening and bound socket should suddenly start refusing connections? Is it something iOS specific? I suspect that iOS might somehow kill listening sockets if an app has been inactive for some time, but shouldn't then the socket handle become invalid and shouldn't accept() return some error immediately instead of waiting for client connection and erroring only after that?
For the server socket I am using FastSocket iOS library, which is just a thin synchronous blocking wrapper around BSD sockets, and everything seems to be pretty standard network programming inside there.
My only hope is some workaround to detect that the server socket was somehow broken and I should close it and recreate with socket(), bind() and listen(). But I have no idea how do I reliably detect this situation in my code because the socket handle seems to be valid and accept is still blocking and waiting for connections, as it should.