diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-09-04 15:29:57 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-09-04 15:29:57 (GMT) |
commit | 874dbe895d94eccbc8eac7214cc7ea86e0d2cb50 (patch) | |
tree | d80c1aad4bd404a2d28d527e12fb450ef68e2152 /Python/pylifecycle.c | |
parent | d529ebb438f61d497b492268e18bc435f57ab735 (diff) | |
parent | 6fb5bae252b90b81dff19f572fe40a9051e5e51d (diff) | |
download | cpython-874dbe895d94eccbc8eac7214cc7ea86e0d2cb50.zip cpython-874dbe895d94eccbc8eac7214cc7ea86e0d2cb50.tar.gz cpython-874dbe895d94eccbc8eac7214cc7ea86e0d2cb50.tar.bz2 |
Merge 3.4 (create_stdio)
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r-- | Python/pylifecycle.c | 79 |
1 files changed, 37 insertions, 42 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index a17adf7..df66fa0 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1,4 +1,3 @@ - /* Python interpreter top-level routines, including init/exit */ #include "Python.h" @@ -963,6 +962,23 @@ initsite(void) } } +/* Check if a file descriptor is valid or not. + Return 0 if the file descriptor is invalid, return non-zero otherwise. */ +static int +is_valid_fd(int fd) +{ + int fd2; + if (fd < 0 || !_PyVerify_fd(fd)) + return 0; + _Py_BEGIN_SUPPRESS_IPH + fd2 = dup(fd); + if (fd2 >= 0) + close(fd2); + _Py_END_SUPPRESS_IPH + return fd2 >= 0; +} + +/* returns Py_None if the fd is not valid */ static PyObject* create_stdio(PyObject* io, int fd, int write_mode, char* name, @@ -978,6 +994,9 @@ create_stdio(PyObject* io, _Py_IDENTIFIER(TextIOWrapper); _Py_IDENTIFIER(mode); + if (!is_valid_fd(fd)) + Py_RETURN_NONE; + /* stdin is always opened in buffered mode, first because it shouldn't make a difference in common use cases, second because TextIOWrapper depends on the presence of a read1() method which only exists on @@ -1059,21 +1078,15 @@ error: Py_XDECREF(stream); Py_XDECREF(text); Py_XDECREF(raw); - return NULL; -} -static int -is_valid_fd(int fd) -{ - int dummy_fd; - if (fd < 0 || !_PyVerify_fd(fd)) - return 0; - _Py_BEGIN_SUPPRESS_IPH - dummy_fd = dup(fd); - if (dummy_fd >= 0) - close(dummy_fd); - _Py_END_SUPPRESS_IPH - return dummy_fd >= 0; + if (PyErr_ExceptionMatches(PyExc_OSError) && !is_valid_fd(fd)) { + /* Issue #24891: the file descriptor was closed after the first + is_valid_fd() check was called. Ignore the OSError and set the + stream to None. */ + PyErr_Clear(); + Py_RETURN_NONE; + } + return NULL; } /* Initialize sys.stdin, stdout, stderr and builtins.open */ @@ -1158,30 +1171,18 @@ initstdio(void) * and fileno() may point to an invalid file descriptor. For example * GUI apps don't have valid standard streams by default. */ - if (!is_valid_fd(fd)) { - std = Py_None; - Py_INCREF(std); - } - else { - std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors); - if (std == NULL) - goto error; - } /* if (fd < 0) */ + std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors); + if (std == NULL) + goto error; PySys_SetObject("__stdin__", std); _PySys_SetObjectId(&PyId_stdin, std); Py_DECREF(std); /* Set sys.stdout */ fd = fileno(stdout); - if (!is_valid_fd(fd)) { - std = Py_None; - Py_INCREF(std); - } - else { - std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors); - if (std == NULL) - goto error; - } /* if (fd < 0) */ + std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors); + if (std == NULL) + goto error; PySys_SetObject("__stdout__", std); _PySys_SetObjectId(&PyId_stdout, std); Py_DECREF(std); @@ -1189,15 +1190,9 @@ initstdio(void) #if 1 /* Disable this if you have trouble debugging bootstrap stuff */ /* Set sys.stderr, replaces the preliminary stderr */ fd = fileno(stderr); - if (!is_valid_fd(fd)) { - std = Py_None; - Py_INCREF(std); - } - else { - std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace"); - if (std == NULL) - goto error; - } /* if (fd < 0) */ + std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace"); + if (std == NULL) + goto error; /* Same as hack above, pre-import stderr's codec to avoid recursion when import.c tries to write to stderr in verbose mode. */ |