eryksun added the comment:

> I guess you were mainly testing with Python 2. Python 3 on Linux 
> does not raise any error either

In Python 3 os.fdopen delegates to io.open, which calls io.FileIO to create the 
raw file object. This doesn't verify a compatible mode on the file descriptor. 
Similarly, in Windows Python 2 os.fdopen calls VC++ _fdopen, which also doesn't 
verify a compatible mode. 

The POSIX spec (IEEE Std 1003.1, 2013 Edition) for fdopen says that "the 
*application* shall ensure that the mode of the stream as expressed by the mode 
argument is allowed by the file access mode of the open file description to 
which fildes refers" [1] (emphasis mine).  It happens that glibc in Linux opts 
to do this check for you.

If instead of closing the underlying file descriptor the program opts to close 
the Python file object or C FILE stream, this will attempt to write the 
buffered string "bbb" to the read-only fd, which should raise an EBADF error. 

[1]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdopen.html

---

The way test_openfd.py directly closes the underlying file descriptor does 
highlight an annoying problem in Python 2 on Windows. This should get its own 
issue in case someone feels like addressing it. The problem is open() and 
os.fdopen() create the file object with fclose as the FILE stream closer. It'd 
be nicer to instead use a closer on Windows that first calls _PyVerify_fd to 
check for a valid file descriptor. Otherwise the CRT asserts and terminates the 
process. For example:

    import os
    f = open('@test')
    os.close(f.fileno())

Functions in posixmodule.c are good about first verifying the file descriptor:

    >>> os.lseek(f.fileno(), 0, os.SEEK_CUR) # calls _PyVerify_fd
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    OSError: [Errno 9] Bad file descriptor

OTOH, closing the file object doesn't verify the file descriptor:

    >>> f.close() # Goodbye cruel world... :'(

Stack trace:

    0:000> k 8
    Child-SP          RetAddr           Call Site
    00000000`0021f3a8 00000000`68e25200 kernel32!TerminateProcessStub
    00000000`0021f3b0 00000000`68e252d4 MSVCR90!invoke_watson+0x11c
    00000000`0021f9a0 00000000`68e1de7e MSVCR90!invalid_parameter+0x70
    00000000`0021f9e0 00000000`68ddf904 MSVCR90!close+0x9e
    00000000`0021fa30 00000000`68ddf997 MSVCR90!fclose_nolock+0x5c
    00000000`0021fa70 00000000`1e0ac2e5 MSVCR90!fclose+0x5f
    00000000`0021fab0 00000000`1e0ac7b2 python27!close_the_file+0xa5
    00000000`0021fae0 00000000`1e114427 python27!file_close+0x12

The problem doesn't exist in Python 3, for which io.FileIO's internal_close 
function is gated by _PyVerify_fd.

----------
nosy: +eryksun
versions: +Python 2.7

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue23634>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to