File descriptor (FD) value increase problem in BSD Socket API calling in iOS

We are getting file descriptor (FD) value using the below BSD socket API in iOS 13.0+ devices.

fd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_STREAM, 0);

In our app, we use this to create a TLS connection in regular intervals, and we always close the previous connection before executing this. in this situation, we found sometimes the same FD value was returned in a subsequent execution of this socket API. Like FD value is getting value 27 in subsequent execution, But sometimes it keeps increasing and it exceeds 1024 value which is making socket execution blocked.

  • What is the logic in iOS for setting this FD value?
  • Even though we close the previous socket why FD value keep on increasing?
  • Is there any way to control the MAX FD value, as it will never exceed 1000?
  • Is there any relation with server and client connection time period, which may cause the FD value increase on the client-side in each new set of TLS connections by using the socket method even though the previous socket was closed?

Note: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/FD_SET.2.html The default size FD_SETSIZE (currently 1024) is somewhat smaller than the current kernel limit to the number of open files. However, in order to accommodate programs that might potentially use a larger number of open files with select, it is possible to increase this size within a program by providing a larger definition of FD_SETSIZE before the inclusion of <sys/types.h>.

  • How to increase the limit of FD_SETSIZE beyond 1024 through overriding the FD_SetSize defined in the sys/types.h?

Is there any reason that you cannot use a higher level API like nw_connection_t for creating a TCP connection and then setting up TLS on that connect? That way you wouldn't have to worry about any of these items and Network Framework will just handle this for you.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

First up, I 100% agree with Matt here. You’d be much better off using Network framework, especially as you’re using TLS. Carrying around your own TLS implementation is not a good idea.


Having said that, I can answer your BSD Sockets questions. You wrote:

But sometimes it keeps increasing and it exceeds 1024 value which is making socket execution blocked.

That means that something in your process is leaking a file descriptor.

What is the logic in iOS for setting this FD value?

It scans the file descriptor table from the bottom and uses the first free entry. The first three items are usually [1] stdin, stdout, and stderr.

This is standard stuff Unix-y stuff that’s required by Posix.

Even though we close the previous socket why FD value keep on increasing?

Because something is leaking file descriptors.

Is there any way to control the MAX FD value, as it will never exceed 1000?

That is not the way to solve this problem. Rather, you should investigate the cause of this leak and plug in.

Is there any relation with server and client connection time period, which may cause the FD value increase on the client-side in each new set of TLS connections by using the socket method even though the previous socket was closed?

Not intrinsically, but there could be a bug in your code that causes it to leak the file descriptor under specific circumstances.

How to increase the limit of FD_SETSIZE beyond 1024 through overriding the FD_SetSize defined in the <sys/types.h>?

Again, bumping up this limit is not the right way to address your problem.


Does this problem reproduce on the simulator? The reason that’s relevant is that the simulator gives you access to more debugging tools (-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] But this is not an absolute requirement.

That means that something in your process is leaking a file descriptor.

It will be very helpful if you please suggest some possible scenarios where fd might leak and to identify the process for fd leaking even though socket close was called. if socket close is called, in iOS side what are the dependencies to make the FD free?

Not intrinsically, but there could be a bug in your code that causes it to leak the file descriptor under specific circumstances.

In 2 different servers, we saw different behavior, while connecting to one server it's normal, not increasing. but it's getting increased in another one. though in both server-client create TLS connection from time to time and every time it closes the socket.

Again, bumping up this limit is not the right way to address your problem. Does this problem reproduce on the simulator? The reason that’s relevant is that the simulator gives you access to more debugging tools (-:

Simulator run is not possible, can you please suggest some way to check from live devices.

It will be very helpful if you please suggest some possible scenarios where fd might leak and to identify the process for fd leaking even though socket close was called.

File descriptors are used for more than just sockets. If you have code that opens a file and fails to close it, you’ll see exactly these symptoms in your BSD Sockets code, because the leaking file descriptors from your file code will cause the file descriptor table to fill up to the detriment of your netowrking code.

Simulator run is not possible

That makes things harder. Any chance you can hack your project to run on the sim? Remember that you don’t need the whole app to run, you just need to reproduce the problem.

If that’s not possible then you have to build your own tooling. The first step is to identify what type of file descriptor is leaking. That ensures that you’re checking the right part of your code for leaks.

A good way to do that is to write debug code that dumps the file descriptor table. See this post for an example of how to do that.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

File descriptor (FD) value increase problem in BSD Socket API calling in iOS
 
 
Q