mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
Merge 3.5 (create_stdio)
This commit is contained in:
commit
d05f49924d
3 changed files with 44 additions and 42 deletions
|
@ -1066,6 +1066,7 @@ Jan Palus
|
||||||
Yongzhi Pan
|
Yongzhi Pan
|
||||||
Martin Panter
|
Martin Panter
|
||||||
Mathias Panzenböck
|
Mathias Panzenböck
|
||||||
|
Marco Paolini
|
||||||
M. Papillon
|
M. Papillon
|
||||||
Peter Parente
|
Peter Parente
|
||||||
Alexandre Parenteau
|
Alexandre Parenteau
|
||||||
|
|
|
@ -101,6 +101,12 @@ Core and Builtins
|
||||||
Library
|
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
|
- Issue #24992: Fix error handling and a race condition (related to garbage
|
||||||
collection) in collections.OrderedDict constructor.
|
collection) in collections.OrderedDict constructor.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/* Python interpreter top-level routines, including init/exit */
|
/* Python interpreter top-level routines, including init/exit */
|
||||||
|
|
||||||
#include "Python.h"
|
#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*
|
static PyObject*
|
||||||
create_stdio(PyObject* io,
|
create_stdio(PyObject* io,
|
||||||
int fd, int write_mode, char* name,
|
int fd, int write_mode, char* name,
|
||||||
|
@ -978,6 +994,9 @@ create_stdio(PyObject* io,
|
||||||
_Py_IDENTIFIER(TextIOWrapper);
|
_Py_IDENTIFIER(TextIOWrapper);
|
||||||
_Py_IDENTIFIER(mode);
|
_Py_IDENTIFIER(mode);
|
||||||
|
|
||||||
|
if (!is_valid_fd(fd))
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
|
||||||
/* stdin is always opened in buffered mode, first because it shouldn't
|
/* stdin is always opened in buffered mode, first because it shouldn't
|
||||||
make a difference in common use cases, second because TextIOWrapper
|
make a difference in common use cases, second because TextIOWrapper
|
||||||
depends on the presence of a read1() method which only exists on
|
depends on the presence of a read1() method which only exists on
|
||||||
|
@ -1059,21 +1078,15 @@ error:
|
||||||
Py_XDECREF(stream);
|
Py_XDECREF(stream);
|
||||||
Py_XDECREF(text);
|
Py_XDECREF(text);
|
||||||
Py_XDECREF(raw);
|
Py_XDECREF(raw);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
if (PyErr_ExceptionMatches(PyExc_OSError) && !is_valid_fd(fd)) {
|
||||||
is_valid_fd(int fd)
|
/* Issue #24891: the file descriptor was closed after the first
|
||||||
{
|
is_valid_fd() check was called. Ignore the OSError and set the
|
||||||
int dummy_fd;
|
stream to None. */
|
||||||
if (fd < 0 || !_PyVerify_fd(fd))
|
PyErr_Clear();
|
||||||
return 0;
|
Py_RETURN_NONE;
|
||||||
_Py_BEGIN_SUPPRESS_IPH
|
}
|
||||||
dummy_fd = dup(fd);
|
return NULL;
|
||||||
if (dummy_fd >= 0)
|
|
||||||
close(dummy_fd);
|
|
||||||
_Py_END_SUPPRESS_IPH
|
|
||||||
return dummy_fd >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize sys.stdin, stdout, stderr and builtins.open */
|
/* 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
|
* and fileno() may point to an invalid file descriptor. For example
|
||||||
* GUI apps don't have valid standard streams by default.
|
* GUI apps don't have valid standard streams by default.
|
||||||
*/
|
*/
|
||||||
if (!is_valid_fd(fd)) {
|
std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors);
|
||||||
std = Py_None;
|
if (std == NULL)
|
||||||
Py_INCREF(std);
|
goto error;
|
||||||
}
|
|
||||||
else {
|
|
||||||
std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors);
|
|
||||||
if (std == NULL)
|
|
||||||
goto error;
|
|
||||||
} /* if (fd < 0) */
|
|
||||||
PySys_SetObject("__stdin__", std);
|
PySys_SetObject("__stdin__", std);
|
||||||
_PySys_SetObjectId(&PyId_stdin, std);
|
_PySys_SetObjectId(&PyId_stdin, std);
|
||||||
Py_DECREF(std);
|
Py_DECREF(std);
|
||||||
|
|
||||||
/* Set sys.stdout */
|
/* Set sys.stdout */
|
||||||
fd = fileno(stdout);
|
fd = fileno(stdout);
|
||||||
if (!is_valid_fd(fd)) {
|
std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors);
|
||||||
std = Py_None;
|
if (std == NULL)
|
||||||
Py_INCREF(std);
|
goto error;
|
||||||
}
|
|
||||||
else {
|
|
||||||
std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors);
|
|
||||||
if (std == NULL)
|
|
||||||
goto error;
|
|
||||||
} /* if (fd < 0) */
|
|
||||||
PySys_SetObject("__stdout__", std);
|
PySys_SetObject("__stdout__", std);
|
||||||
_PySys_SetObjectId(&PyId_stdout, std);
|
_PySys_SetObjectId(&PyId_stdout, std);
|
||||||
Py_DECREF(std);
|
Py_DECREF(std);
|
||||||
|
@ -1189,15 +1190,9 @@ initstdio(void)
|
||||||
#if 1 /* Disable this if you have trouble debugging bootstrap stuff */
|
#if 1 /* Disable this if you have trouble debugging bootstrap stuff */
|
||||||
/* Set sys.stderr, replaces the preliminary stderr */
|
/* Set sys.stderr, replaces the preliminary stderr */
|
||||||
fd = fileno(stderr);
|
fd = fileno(stderr);
|
||||||
if (!is_valid_fd(fd)) {
|
std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace");
|
||||||
std = Py_None;
|
if (std == NULL)
|
||||||
Py_INCREF(std);
|
goto error;
|
||||||
}
|
|
||||||
else {
|
|
||||||
std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace");
|
|
||||||
if (std == NULL)
|
|
||||||
goto error;
|
|
||||||
} /* if (fd < 0) */
|
|
||||||
|
|
||||||
/* Same as hack above, pre-import stderr's codec to avoid recursion
|
/* Same as hack above, pre-import stderr's codec to avoid recursion
|
||||||
when import.c tries to write to stderr in verbose mode. */
|
when import.c tries to write to stderr in verbose mode. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue