diff options
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst | 2 | ||||
-rw-r--r-- | Python/pylifecycle.c | 38 |
2 files changed, 25 insertions, 15 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst new file mode 100644 index 0000000..6a9a85c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst @@ -0,0 +1,2 @@ +Fix Python Initialization code on FreeBSD to detect properly when stdin file +descriptor (fd 0) is invalid. diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index ad14472..c7920ef 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1664,26 +1664,34 @@ initsite(void) static int is_valid_fd(int fd) { -#ifdef __APPLE__ - /* bpo-30225: On macOS Tiger, when stdout is redirected to a pipe - and the other side of the pipe is closed, dup(1) succeed, whereas - fstat(1, &st) fails with EBADF. Prefer fstat() over dup() to detect - such error. */ - struct stat st; - return (fstat(fd, &st) == 0); -#else - int fd2; - if (fd < 0) +/* dup() is faster than fstat(): fstat() can require input/output operations, + whereas dup() doesn't. There is a low risk of EMFILE/ENFILE at Python + startup. Problem: dup() doesn't check if the file descriptor is valid on + some platforms. + + bpo-30225: On macOS Tiger, when stdout is redirected to a pipe and the other + side of the pipe is closed, dup(1) succeed, whereas fstat(1, &st) fails with + EBADF. FreeBSD has similar issue (bpo-32849). + + Only use dup() on platforms where dup() is enough to detect invalid FD in + corner cases: on Linux and Windows (bpo-32849). */ +#if defined(__linux__) || defined(MS_WINDOWS) + if (fd < 0) { return 0; + } + int fd2; + _Py_BEGIN_SUPPRESS_IPH - /* Prefer dup() over fstat(). fstat() can require input/output whereas - dup() doesn't, there is a low risk of EMFILE/ENFILE at Python - startup. */ fd2 = dup(fd); - if (fd2 >= 0) + if (fd2 >= 0) { close(fd2); + } _Py_END_SUPPRESS_IPH - return fd2 >= 0; + + return (fd2 >= 0); +#else + struct stat st; + return (fstat(fd, &st) == 0); #endif } |