Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-32849: Fix is_valid_fd() on FreeBSD #12852

Merged
merged 1 commit into from
Apr 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
bpo-32849: Fix is_valid_fd() on FreeBSD
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.
  • Loading branch information
vstinner committed Apr 16, 2019
commit f9c01a16dae8aa15d264a1937fb589e8598d1c88
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix Python Initialization code on FreeBSD to detect properly when stdin file
descriptor (fd 0) is invalid.
38 changes: 23 additions & 15 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -1664,26 +1664,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
}

Expand Down