Reputation: 365
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.
Upvotes: 5
Views: 494
Reputation: 1865
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!
Upvotes: 2