SUMMARY Valgrind uses open file limits in effect when valgrind starts, ignoring the changes made my the debugged program. STEPS TO REPRODUCE $ cat many-files.c #include <assert.h> #include <unistd.h> #include <sys/time.h> #include <sys/resource.h> int main (int argc, char ** argv) { int i; struct rlimit rlim; getrlimit(RLIMIT_NOFILE, &rlim); assert(rlim.rlim_cur <= 1024); rlim.rlim_cur = 2048; setrlimit(RLIMIT_NOFILE, &rlim); for (i = 4; i < 1028; i++) { dup2(1, i); } for (i = 4; i < 1028; i++) { close(i); } return 1; } $ gcc many-files.c $ valgrind ./a.out OBSERVED RESULT ==3814075== Memcheck, a memory error detector ==3814075== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==3814075== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==3814075== Command: ./a.out ==3814075== ==3814075== Warning: invalid file descriptor 1024 in syscall dup2() ==3814075== Warning: invalid file descriptor 1025 in syscall dup2() ==3814075== Warning: invalid file descriptor 1026 in syscall dup2() ==3814075== Warning: invalid file descriptor 1027 in syscall dup2() ==3814075== Use --log-fd=<number> to select an alternative log fd. ==3814075== Warning: invalid file descriptor 1024 in syscall close() ==3814075== Warning: invalid file descriptor 1025 in syscall close() ==3814075== Warning: invalid file descriptor 1026 in syscall close() ==3814075== Warning: invalid file descriptor 1027 in syscall close() ==3814075== Use --log-fd=<number> to select an alternative log fd. ==3814075== ==3814075== HEAP SUMMARY: ==3814075== in use at exit: 0 bytes in 0 blocks ==3814075== total heap usage: 0 allocs, 0 frees, 0 bytes allocated ==3814075== ==3814075== All heap blocks were freed -- no leaks are possible ==3814075== ==3814075== For lists of detected and suppressed errors, rerun with: -s ==3814075== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) EXPECTED RESULT Valgrind notices RLIMIT_NOFILE changes and uses the new limit in fd validity check. SOFTWARE/OS VERSIONS Linux/KDE Plasma: Ubuntu 20.04 Valgrind: valgrind-3.15.0
Because valgrind has to reserve some file descriptors for it's own use at the top of the range it is not able to honour all requests to increase limits. What were the soft and hard limits when your program started?
$ ulimit -S -n 1024 $ ulimit -H -n 1048576
Right to basically what valgrind does is that it increases the soft limit by the number of descriptors it wants to reserve for itself, and then lowers the emulated soft and hard limits to the soft limit. So you should find that your first getrlimit actually reports a hard limit of 1024 as well as a soft limit of 1024 and that your setrlimit fails. So basically this is one place where the emulated environment is not quite the same as the host environment, but if you pay attention to system call results you should get results which match the emulated environment. If you need more descriptors when running under valgrind then you will need to raise the soft limit before starting it.
I don't see a problem here - it's the way that Valgrind works.