Skip to content

Commit 0d3a911

Browse files
committed
bpo-45915: use fcntl(fd, F_GETFD) in is_valid_fd()
Signed-off-by: Christian Heimes <[email protected]>
1 parent 46c8d91 commit 0d3a911

File tree

2 files changed

+14
-0
lines changed

2 files changed

+14
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``is_valid_fd`` now uses faster ``fcntl(fd, F_GETFD)`` on Linux and Windows.

Python/pylifecycle.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
# include <langinfo.h> // nl_langinfo(CODESET)
3131
#endif
3232

33+
#ifdef HAVE_FCNTL_H
34+
# include <fcntl.h> // F_GETFD
35+
#endif
36+
3337
#ifdef MS_WINDOWS
3438
# undef BYTE
3539
# include "windows.h"
@@ -2129,6 +2133,8 @@ is_valid_fd(int fd)
21292133
startup. Problem: dup() doesn't check if the file descriptor is valid on
21302134
some platforms.
21312135
2136+
fcntl(fd, F_GETFD) is even faster, because it only checks the process table.
2137+
21322138
bpo-30225: On macOS Tiger, when stdout is redirected to a pipe and the other
21332139
side of the pipe is closed, dup(1) succeed, whereas fstat(1, &st) fails with
21342140
EBADF. FreeBSD has similar issue (bpo-32849).
@@ -2139,6 +2145,12 @@ is_valid_fd(int fd)
21392145
if (fd < 0) {
21402146
return 0;
21412147
}
2148+
#ifdef F_GETFD
2149+
_Py_BEGIN_SUPPRESS_IPH
2150+
int res = fcntl(fd, F_GETFD);
2151+
_Py_END_SUPPRESS_IPH
2152+
return res >= 0;
2153+
#else
21422154
int fd2;
21432155

21442156
_Py_BEGIN_SUPPRESS_IPH
@@ -2149,6 +2161,7 @@ is_valid_fd(int fd)
21492161
_Py_END_SUPPRESS_IPH
21502162

21512163
return (fd2 >= 0);
2164+
#endif /* F_GETFD */
21522165
#else
21532166
struct stat st;
21542167
return (fstat(fd, &st) == 0);

0 commit comments

Comments
 (0)