iOS listen socket become bad file descriptor after screen lock

Viewed 1856

I use a TCP server(just bind to 127.0.0.1 and a random port) for some reason(cross-platform related) in my App. I use the posix function select to check if there is a new tcp connection. It works fine most time, but when I : 1) press home button, lock screen. 2) unlock screen, press App icon go back to App right away.

The select function returns, tells me I can handle my server socket, after I call accept function, it returns -1, and then I check the SO_ERROR by getsockopt, return the error EBADF. Codes below:

//listen fd is already nonblocking
if ((*pa = accept(*ps, addr, len)) != -1){
    printf("after accept %d %d\n", *pa, errno);
    return IO_DONE;
}

printf("after accept error %d %d %d %s\n", *ps, *pa, errno, strerror(errno));

int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (*ps, SOL_SOCKET, SO_ERROR, &error, &len);
if (retval != 0) {
    /* there was a problem getting the error code */
    fprintf(stderr, "error getting socket error code: %s\n", strerror(retval));
}

if (error != 0) {
    /* socket has a non zero error status */
    fprintf(stderr, "socket error: %s\n", strerror(error));
}

log:

after accept error 5 -1 35 Resource temporarily unavailable
socket error: Bad file descriptor

My Test Device is a iPhone 4s, OS version is iOS 8.4.1

I have already https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/CommonPitfalls/CommonPitfalls.html and I have not found anything wrong.

So, Why this happen and how to solve?

2 Answers

https://developer.apple.com/library/archive/technotes/tn2277/_index.html

Listening Socket Handling a listening socket in a multitasking environment is very simple: your app should close the listening socket when it goes into the background and reopen it when it comes back into the foreground. There are two important reasons for this:

Once your app goes into the background, it may be suspended. Once it is suspended, it's unable to properly process incoming connections on the listening socket. However, the socket is still active as far as the kernel is concerned. If a client connects to the socket, the kernel will accept the connection but your app won't communicate over it. Eventually the client will give up, but that might take a while. Thus, it's better to close the listening socket when going into the background, which will cause incoming connections to be immediately rejected by the kernel.

If the system suspends your app and then, later on, reclaims the resources from underneath your listening socket, your app will no longer be listening for connections, even after it has been resumed. The app may or may not be notified of this, depending on how it manages the listening socket. It's generally easier to avoid this problem entirely by closing the listening socket when the app is in the background. Keep in mind that, when your app closes a listening socket, it should also stop any Bonjour registrations for that socket.

Related