Skip to content

Commit b87a807

Browse files
bpo-32849: Fix is_valid_fd() on FreeBSD (GH-12852) (GH-12863)
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 3092d6b) Co-authored-by: Victor Stinner <vstinner@redhat.com>
1 parent a6fce19 commit b87a807

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix Python Initialization code on FreeBSD to detect properly when stdin file
2+
descriptor (fd 0) is invalid.

Python/pylifecycle.c

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,26 +1672,34 @@ initsite(void)
16721672
static int
16731673
is_valid_fd(int fd)
16741674
{
1675-
#ifdef __APPLE__
1676-
/* bpo-30225: On macOS Tiger, when stdout is redirected to a pipe
1677-
and the other side of the pipe is closed, dup(1) succeed, whereas
1678-
fstat(1, &st) fails with EBADF. Prefer fstat() over dup() to detect
1679-
such error. */
1680-
struct stat st;
1681-
return (fstat(fd, &st) == 0);
1682-
#else
1683-
int fd2;
1684-
if (fd < 0)
1675+
/* dup() is faster than fstat(): fstat() can require input/output operations,
1676+
whereas dup() doesn't. There is a low risk of EMFILE/ENFILE at Python
1677+
startup. Problem: dup() doesn't check if the file descriptor is valid on
1678+
some platforms.
1679+
1680+
bpo-30225: On macOS Tiger, when stdout is redirected to a pipe and the other
1681+
side of the pipe is closed, dup(1) succeed, whereas fstat(1, &st) fails with
1682+
EBADF. FreeBSD has similar issue (bpo-32849).
1683+
1684+
Only use dup() on platforms where dup() is enough to detect invalid FD in
1685+
corner cases: on Linux and Windows (bpo-32849). */
1686+
#if defined(__linux__) || defined(MS_WINDOWS)
1687+
if (fd < 0) {
16851688
return 0;
1689+
}
1690+
int fd2;
1691+
16861692
_Py_BEGIN_SUPPRESS_IPH
1687-
/* Prefer dup() over fstat(). fstat() can require input/output whereas
1688-
dup() doesn't, there is a low risk of EMFILE/ENFILE at Python
1689-
startup. */
16901693
fd2 = dup(fd);
1691-
if (fd2 >= 0)
1694+
if (fd2 >= 0) {
16921695
close(fd2);
1696+
}
16931697
_Py_END_SUPPRESS_IPH
1694-
return fd2 >= 0;
1698+
1699+
return (fd2 >= 0);
1700+
#else
1701+
struct stat st;
1702+
return (fstat(fd, &st) == 0);
16951703
#endif
16961704
}
16971705

0 commit comments

Comments
 (0)