@@ -2410,54 +2410,6 @@ init_import_site(void)
24102410 return _PyStatus_OK ();
24112411}
24122412
2413- /* Check if a file descriptor is valid or not.
2414- Return 0 if the file descriptor is invalid, return non-zero otherwise. */
2415- static int
2416- is_valid_fd (int fd )
2417- {
2418- /* dup() is faster than fstat(): fstat() can require input/output operations,
2419- whereas dup() doesn't. There is a low risk of EMFILE/ENFILE at Python
2420- startup. Problem: dup() doesn't check if the file descriptor is valid on
2421- some platforms.
2422-
2423- fcntl(fd, F_GETFD) is even faster, because it only checks the process table.
2424- It is preferred over dup() when available, since it cannot fail with the
2425- "too many open files" error (EMFILE).
2426-
2427- bpo-30225: On macOS Tiger, when stdout is redirected to a pipe and the other
2428- side of the pipe is closed, dup(1) succeed, whereas fstat(1, &st) fails with
2429- EBADF. FreeBSD has similar issue (bpo-32849).
2430-
2431- Only use dup() on Linux where dup() is enough to detect invalid FD
2432- (bpo-32849).
2433- */
2434- if (fd < 0 ) {
2435- return 0 ;
2436- }
2437- #if defined(F_GETFD ) && ( \
2438- defined(__linux__ ) || \
2439- defined(__APPLE__ ) || \
2440- defined(__wasm__ ))
2441- return fcntl (fd , F_GETFD ) >= 0 ;
2442- #elif defined(__linux__ )
2443- int fd2 = dup (fd );
2444- if (fd2 >= 0 ) {
2445- close (fd2 );
2446- }
2447- return (fd2 >= 0 );
2448- #elif defined(MS_WINDOWS )
2449- HANDLE hfile ;
2450- _Py_BEGIN_SUPPRESS_IPH
2451- hfile = (HANDLE )_get_osfhandle (fd );
2452- _Py_END_SUPPRESS_IPH
2453- return (hfile != INVALID_HANDLE_VALUE
2454- && GetFileType (hfile ) != FILE_TYPE_UNKNOWN );
2455- #else
2456- struct stat st ;
2457- return (fstat (fd , & st ) == 0 );
2458- #endif
2459- }
2460-
24612413/* returns Py_None if the fd is not valid */
24622414static PyObject *
24632415create_stdio (const PyConfig * config , PyObject * io ,
@@ -2471,8 +2423,9 @@ create_stdio(const PyConfig *config, PyObject* io,
24712423 int buffering , isatty ;
24722424 const int buffered_stdio = config -> buffered_stdio ;
24732425
2474- if (!is_valid_fd (fd ))
2426+ if (!_Py_IsValidFD (fd )) {
24752427 Py_RETURN_NONE ;
2428+ }
24762429
24772430 /* stdin is always opened in buffered mode, first because it shouldn't
24782431 make a difference in common use cases, second because TextIOWrapper
@@ -2588,9 +2541,9 @@ create_stdio(const PyConfig *config, PyObject* io,
25882541 Py_XDECREF (text );
25892542 Py_XDECREF (raw );
25902543
2591- if (PyErr_ExceptionMatches (PyExc_OSError ) && !is_valid_fd (fd )) {
2544+ if (PyErr_ExceptionMatches (PyExc_OSError ) && !_Py_IsValidFD (fd )) {
25922545 /* Issue #24891: the file descriptor was closed after the first
2593- is_valid_fd () check was called. Ignore the OSError and set the
2546+ _Py_IsValidFD () check was called. Ignore the OSError and set the
25942547 stream to None. */
25952548 PyErr_Clear ();
25962549 Py_RETURN_NONE ;
0 commit comments