]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-32849: Fix is_valid_fd() on FreeBSD (GH-12852) (GH-12863)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 17 Apr 2019 16:30:27 +0000 (09:30 -0700)
committerVictor Stinner <vstinner@redhat.com>
Wed, 17 Apr 2019 16:30:27 +0000 (18:30 +0200)
Fix Python Initialization code on FreeBSD to detect properly when
stdin file descriptor (fd 0) is invalid.

On FreeBSD, fstat() must be used to check if stdin (fd 0) is valid.
dup(0) doesn't fail if stdin is invalid in some cases.
(cherry picked from commit 3092d6b2630e4d2bd200fbc3231c27a7cba4d6b2)

Co-authored-by: Victor Stinner <vstinner@redhat.com>
Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst [new file with mode: 0644]
Python/pylifecycle.c

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 (file)
index 0000000..6a9a85c
--- /dev/null
@@ -0,0 +1,2 @@
+Fix Python Initialization code on FreeBSD to detect properly when stdin file
+descriptor (fd 0) is invalid.
index d8e6f8fa8995538093b429be4f79e69618c7cb58..55d1ba5734434a2eaac4bba58c5c2b7a7bbdf946 100644 (file)
@@ -1672,26 +1672,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
 }