Merge 3.4 (create_stdio)

This commit is contained in:
Victor Stinner 2015-09-04 17:29:57 +02:00
commit 874dbe895d
3 changed files with 44 additions and 42 deletions

View file

@ -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. */