RLIMIT_NOFILE: the maximum number of open files or the maximum fd index?
Subsystems (2)
RFC 1/1 RLIMIT_NOFILE: the maximum number of open files or the maximum fd index?
I always thought that RLIMIT_NOFILE limits the number of open files, but when I
read the code for alloc_fd(), I found that RLIMIT_NOFILE is the largest fd index?
Is this a mistake in my understanding, or is it a code implementation error?
-----
alloc_fd code:
fs/file.c +1 -0
@@ -561,6 +561,7 @@ static int alloc_fd(unsigned start, unsigned end, unsigned flags)*/ error = -EMFILE ;if (unlikely (fd >= end)) +// There may be unclosed fd between [end, max]. the number of open files can be greater than RLIMIT_NOFILE. goto out;
if (unlikely(fd >= fdt->max_fds)) {-----
Test Procedure
1. ulimit -n 1024.
2. Create 1000 FDs.
3. ulimit -n 100.
4. Close all FDs less than 100 and continue to hold FDs greater than 100.
5. Open() and check whether the FD is successfully created,
If RLIMIT_NOFILE is the upper limit of the number of opened files, step 5 should fail, but step 5 returns success.
-----
test code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int fd, i;
struct rlimit rl;
rl.rlim_cur = 1024;
rl.rlim_max = 1024;
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
perror("setrlimit");
exit(EXIT_FAILURE);
}
for (i = 0; i < 1000; i++) {
fd = open("/dev/null", O_RDWR | O_CLOEXEC);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
}
rl.rlim_cur = 100;
rl.rlim_max = 100;
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
perror("setrlimit");
exit(EXIT_FAILURE);
}
for (i = 3; i < 100; i++) {
close(i);
}
fd = open("/dev/null", O_RDWR | O_CLOEXEC);
if (fd == -1) {
if (errno == EMFILE) {
printf("ok\n");
return 0;
} else {
perror("open");
exit(EXIT_FAILURE);
}
} else {
printf("fail: {OPEN_MAX} file descriptors are currently open in the calling process, but open() still returns a success\n");
return -1;
}
return 0;
}----
Best regards,
Xiaoming Ni
Quoted 23 lines · Nixiaoming
I always thought that
RLIMIT_NOFILElimits the number of open files, but when I
read the code foralloc_fd(), I found thatRLIMIT_NOFILEis the largest fd index?
Is this a mistake in my understanding, or is it a code implementation error?-----
alloc_fdcode:fs/file.c +1
-1@@ -561,6 +561,7 @@ static int alloc_fd(unsigned start, unsigned end, unsigned flags)*/ error = -EMFILE ;if (unlikely (fd >= end)) +// There may be unclosed fd between [end, max]. the number of open files can be greater than RLIMIT_NOFILE. goto out;if (unlikely (fd >= fdt->max_fds)) { -----
Quoted 9 lines
Test Procedure
1. ulimit -n 1024.
2. Create 1000 FDs.
3. ulimit -n 100.
4. Close all FDs less than 100 and continue to hold FDs greater than 100.
5.Open()and check whether the FD is successfully created,If
RLIMIT_NOFILEis the upper limit of the number of opened files, step 5 should fail, but step 5 returns success.
This is the expected behavior, albeit posix is a little sketchy about the description:
https://pubs.opengroup.org/onlinepubs/009696699/functions/getrlimit.html
Quoted 6 lines
RLIMIT_NOFILE
This is a number one greater than the maximum value that the system may assign to a newly-created descriptor. If this limit is exceeded, functions that allocate a file descriptor shall fail with errno set to [EMFILE]. This limit constrains the number of file descriptors that a process may allocate.
Since you freed up values in the range fitting the limit, allocation was allowed to succeed.
Note other systems act the same way, nobody is explicitly counting used fds for NOFILE enforcement and per the above they should not.
Ultimately it *does* constrain the number of file descriptors a process may allocate if you take a look at all values present during the lifetime of the process.