From: Christian Heimes Date: Sun, 28 Nov 2021 18:40:27 +0000 (+0200) Subject: bpo-45915: use fcntl(fd, F_GETFD) in is_valid_fd() (GH-29821) X-Git-Tag: v3.11.0a3~106 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f87ea0350286837e9e96de03f8bfa215176c2928;p=thirdparty%2FPython%2Fcpython.git bpo-45915: use fcntl(fd, F_GETFD) in is_valid_fd() (GH-29821) --- diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-28-11-25-08.bpo-45915.TSGcLF.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-28-11-25-08.bpo-45915.TSGcLF.rst new file mode 100644 index 000000000000..aa268f453331 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-28-11-25-08.bpo-45915.TSGcLF.rst @@ -0,0 +1 @@ +``is_valid_fd`` now uses faster ``fcntl(fd, F_GETFD)`` on Linux, macOS, and Windows. diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 7e6060e4ebcf..74d269b7a564 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -30,6 +30,10 @@ # include // nl_langinfo(CODESET) #endif +#ifdef HAVE_FCNTL_H +# include // F_GETFD +#endif + #ifdef MS_WINDOWS # undef BYTE # include "windows.h" @@ -2129,18 +2133,26 @@ is_valid_fd(int fd) startup. Problem: dup() doesn't check if the file descriptor is valid on some platforms. + fcntl(fd, F_GETFD) is even faster, because it only checks the process table. + 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) + corner cases: on Linux and Windows (bpo-32849). +*/ if (fd < 0) { return 0; } +#if defined(F_GETFD) && (defined(__linux__) || defined(__APPLE__) || defined(MS_WINDOWS)) + int res; + _Py_BEGIN_SUPPRESS_IPH + res = fcntl(fd, F_GETFD); + _Py_END_SUPPRESS_IPH + return res >= 0; +#elif defined(__linux__) || defined(MS_WINDOWS) int fd2; - _Py_BEGIN_SUPPRESS_IPH fd2 = dup(fd); if (fd2 >= 0) {