on iOS/iPhone: "Too many open files": need to list open files (like lsof)
Solution 1:
#import <sys/types.h>
#import <fcntl.h>
#import <errno.h>
#import <sys/param.h>
+(void) lsof
{
int flags;
int fd;
char buf[MAXPATHLEN+1] ;
int n = 1 ;
for (fd = 0; fd < (int) FD_SETSIZE; fd++) {
errno = 0;
flags = fcntl(fd, F_GETFD, 0);
if (flags == -1 && errno) {
if (errno != EBADF) {
return ;
}
else
continue;
}
fcntl(fd , F_GETPATH, buf ) ;
NSLog( @"File Descriptor %d number %d in use for: %s",fd,n , buf ) ;
++n ;
}
}
Solution 2:
For future reference, I ran into a similar problem on an iPhone 11 with iOS 13; I was creating too many file descriptors (FDs) by creating too many files and sockets. My solution was to increase FDs at runtime with setrlimit()
.
First I got the FD limits on my iPhone 11, with the following code:
// This goes somewhere in your code
struct rlimit rlim;
if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
std::cout << "Soft limit: " << rlim.rlim_cur << std::endl;
std::cout << "Hard limit: " << rlim.rlim_max << std::endl;
} else {
std::cout << "Unable to get file descriptor limits" << std::endl;
}
After running getrlimit()
, I could confirm that on iOS 13, the soft limit is 256 FDs, and the hard limit is infinite FDs. Since I was creating > 300 FDs between files and sockets, my app was crashing.
In my case I couldn't decrease the number of FDs, so I decided to increase the FD soft limit instead, with this code:
// This goes somewhere in your code
struct rlimit rlim;
rlim.rlim_cur = NEW_SOFT_LIMIT;
rlim.rlim_max = NEW_HARD_LIMIT;
if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
std::cout << "Unable to set file descriptor limits" << std::endl;
}
NOTE: You can find more information on gettrlimit()
and setrlimit()
here and here.
Solution 3:
Can you reproduce the problem running in the simulator?
If so, then you could actually use "lsof"...
update:
Ok, if you can't use the simulator, then idea #2:
When you get the "too many open files" error, call a function that iterates through all open file descriptors and dumps some information about each (for example the length and the first few bytes).
Solution 4:
Can't you just intercept all file opens with your own function, say my_fopen
, and store the descriptors along with their names so that when you have too many files opened, you can go through your list to see what's taking all the descriptors?