mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Merge 3.4 (create_stdio)
This commit is contained in:
commit
874dbe895d
3 changed files with 44 additions and 42 deletions
|
@ -1066,6 +1066,7 @@ Jan Palus
|
|||
Yongzhi Pan
|
||||
Martin Panter
|
||||
Mathias Panzenböck
|
||||
Marco Paolini
|
||||
M. Papillon
|
||||
Peter Parente
|
||||
Alexandre Parenteau
|
||||
|
|
|
@ -14,6 +14,12 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #24891: Fix a race condition at Python startup if the file descriptor
|
||||
of stdin (0), stdout (1) or stderr (2) is closed while Python is creating
|
||||
sys.stdin, sys.stdout and sys.stderr objects. These attributes are now set
|
||||
to None if the creation of the object failed, instead of raising an OSError
|
||||
exception. Initial patch written by Marco Paolini.
|
||||
|
||||
- Issue #24992: Fix error handling and a race condition (related to garbage
|
||||
collection) in collections.OrderedDict constructor.
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue