Skip to content

Commit

Permalink
bpo-45915: use fcntl(fd, F_GETFD) in is_valid_fd() (GH-29821)
Browse files Browse the repository at this point in the history
  • Loading branch information
tiran authored Nov 28, 2021
1 parent aaf4222 commit f87ea03
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``is_valid_fd`` now uses faster ``fcntl(fd, F_GETFD)`` on Linux, macOS, and Windows.
18 changes: 15 additions & 3 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit f87ea03

Please sign in to comment.