Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens to file descriptors in Python 3 when .close() fails?

The following Python 3 code exhibits some strange behavior (to me, at least) when I run it through strace:

import os
import sys

if len(sys.argv) != 2:
    print('Usage: ecpy <filename>')
sys.exit(1)
try:
    print('my PID: %d' % os.getpid())
    with open(sys.argv[1], 'w') as fp:
        try:
            fp.write('Hello Stack Overflow!')
        except IOError as e:
            print('### before close')
            print(str(e))
            sys.stdout.flush()
except IOError as e:
    print('### after close')
    print(str(e))
    sys.stdout.flush()

print('### after exception block')
sys.stdout.flush()

Since I/O is buffered, if you run this code with /dev/full, it doesn't fail until fp closes at the end of the with block. That's no surprise. In Python 2.7.3rc2 (on my system), the code runs the exception handler after actually closing the file descriptor corresponding to fp:

write(3, "Hello Stack Overflow!", 21)   = -1 ENOSPC (No space left on device)
close(3)                                = 0
munmap(0x7f9de3f78000, 4096)            = 0
write(1, "### after close\n", 16)       = 16
write(1, "[Errno 28] No space left on devi"..., 35) = 35
write(1, "### after exception block\n", 26) = 26

However, in Python 3.2.3 (on my system), the file descriptor is still open after the exception block runs:

write(3, "Hello Stack Overflow!", 21)   = -1 ENOSPC (No space left on device)
write(1, "### after close\n", 16)       = 16
write(1, "[Errno 28] No space left on devi"..., 35) = 35
write(1, "### after exception block\n", 26) = 26
...
write(3, "Hello Stack Overflow!", 21)   = -1 ENOSPC (No space left on device)
write(3, "Hello Stack Overflow!", 21)   = -1 ENOSPC (No space left on device)
close(3)                                = 0

The interpreter tries to write to the file a few more times and fails silently. When does Python actually call close()? What is invoking it? This behavior seems to leak a file descriptor.

like image 441
Samuel Isaacson Avatar asked Nov 04 '22 09:11

Samuel Isaacson


1 Answers

I took the liberty of submitting an issue to bugs.python.org, let's wait and see if it pans out.

http://bugs.python.org/issue16597

EDIT: Looks like it's a bug, good catch!

like image 123
udoprog Avatar answered Nov 10 '22 17:11

udoprog