[Python-checkins] bpo-45915: use fcntl(fd, F_GETFD) in is_valid_fd() (GH-29821)

tiran webhook-mailer at python.org
Sun Nov 28 13:40:40 EST 2021


https://github.com/python/cpython/commit/f87ea0350286837e9e96de03f8bfa215176c2928
commit: f87ea0350286837e9e96de03f8bfa215176c2928
branch: main
author: Christian Heimes <christian at python.org>
committer: tiran <christian at python.org>
date: 2021-11-28T19:40:27+01:00
summary:

bpo-45915: use fcntl(fd, F_GETFD) in is_valid_fd() (GH-29821)

files:
A Misc/NEWS.d/next/Core and Builtins/2021-11-28-11-25-08.bpo-45915.TSGcLF.rst
M Python/pylifecycle.c

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 0000000000000..aa268f4533310
--- /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 7e6060e4ebcf7..74d269b7a5646 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -30,6 +30,10 @@
 #  include <langinfo.h>           // nl_langinfo(CODESET)
 #endif
 
+#ifdef HAVE_FCNTL_H
+#  include <fcntl.h>              // 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) {



More information about the Python-checkins mailing list