diff -r cc15d736d860 Python/pylifecycle.c --- a/Python/pylifecycle.c Mon Aug 24 20:31:53 2015 -0700 +++ b/Python/pylifecycle.c Fri Sep 04 13:07:42 2015 +0200 @@ -1,4 +1,3 @@ - /* Python interpreter top-level routines, including init/exit */ #include "Python.h" @@ -1076,6 +1075,32 @@ return dummy_fd >= 0; } + +static PyObject* +create_stdio_checked(PyObject* io, + int fd, int write_mode, char* name, + char* encoding, char* errors) +{ + PyObject * std; + + if (!is_valid_fd(fd)) { + std = Py_None; + Py_INCREF(std); + return std; + } + std = create_stdio(io, fd, write_mode, name, encoding, errors); + if (std == NULL) { + /* Protect from a race condition when fd becomes invalid aftter + the first check and before the create_stdio call + */ + if (!is_valid_fd(fd)) { + std = Py_None; + Py_INCREF(std); + } + } + return std; +} + /* Initialize sys.stdin, stdout, stderr and builtins.open */ static int initstdio(void) @@ -1158,30 +1183,18 @@ * 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, "", encoding, errors); - if (std == NULL) - goto error; - } /* if (fd < 0) */ + std = create_stdio_checked(iomod, fd, 0, "", 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, "", encoding, errors); - if (std == NULL) - goto error; - } /* if (fd < 0) */ + std = create_stdio_checked(iomod, fd, 1, "", encoding, errors); + if (std == NULL) + goto error; PySys_SetObject("__stdout__", std); _PySys_SetObjectId(&PyId_stdout, std); Py_DECREF(std); @@ -1189,15 +1202,9 @@ #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, "", encoding, "backslashreplace"); - if (std == NULL) - goto error; - } /* if (fd < 0) */ + std = create_stdio_checked(iomod, fd, 1, "", 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. */