I wrote kind of a test suite which is heavily file intensive. After some time (2h) I get an IOError: [Errno 24] Too many open files: '/tmp/tmpxsqYPm'
. I double checked all file handles whether I close them again. But the error still exists.
I tried to figure out the number of allowed file descriptors using resource.RLIMIT_NOFILE
and the number of currently opened file desciptors:
def get_open_fds(): fds = [] for fd in range(3,resource.RLIMIT_NOFILE): try: flags = fcntl.fcntl(fd, fcntl.F_GETFD) except IOError: continue fds.append(fd) return fds
So if I run the following test:
print get_open_fds() for i in range(0,100): f = open("/tmp/test_%i" % i, "w") f.write("test") print get_open_fds()
I get this output:
[] /tmp/test_0 [3] /tmp/test_1 [4] /tmp/test_2 [3] /tmp/test_3 [4] /tmp/test_4 [3] /tmp/test_5 [4] ...
That's strange, I expected an increasing number of opened file descriptors. Is my script correct?
I'm using python's logger and subprocess. Could that be the reason for my fd leak?
Thanks, Daniel
The Too many open files message occurs on UNIX and Linux operating systems. The default setting for the maximum number of open files might be too low. To avoid this condition, increase the maximum open files to 8000 : Edit the /etc/security/limit.
There is no way in python natively to track all opened files. To do that you should either track all the files yourself or always use the with statement to open files which automatically closes the file as it goes out of scope or encounters an error.
"Too many open files " errors happen when a process needs to open more files than it is allowed by the operating system. This number is controlled by the maximum number of file descriptors the process has. 2. Explicitly set the number of file descriptors using the ulimit command.
The corrected code is:
import resource import fcntl import os def get_open_fds(): fds = [] soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE) for fd in range(0, soft): try: flags = fcntl.fcntl(fd, fcntl.F_GETFD) except IOError: continue fds.append(fd) return fds def get_file_names_from_file_number(fds): names = [] for fd in fds: names.append(os.readlink('/proc/self/fd/%d' % fd)) return names fds = get_open_fds() print get_file_names_from_file_number(fds)
Your test script overwrites f
each iteration, which means that the file will get closed each time. Both logging to files and subprocess
with pipes use up descriptors, which can lead to exhaustion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With