From: Victor Stinner Date: Tue, 25 Jul 2017 15:45:53 +0000 (+0200) Subject: bpo-31009: Fix support.fd_count() on Windows (#2862) X-Git-Tag: v3.7.0a1~370 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=302bbbe9ba5c72559913e2ea006c921f698a729d;p=python bpo-31009: Fix support.fd_count() on Windows (#2862) * bpo-31009: Fix support.fd_count() on Windows On Windows, test.support.fd_count() now calls msvcrt.CrtSetReportMode() to not kill the process nor log any error on stderr on os.dup(fd) if the file descriptor is invalid. * Fix for release mode --- diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 3a4d27e6b8..7a4671c1b2 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2649,12 +2649,6 @@ def disable_faulthandler(): faulthandler.enable(file=fd, all_threads=True) -try: - MAXFD = os.sysconf("SC_OPEN_MAX") -except Exception: - MAXFD = 256 - - def fd_count(): """Count the number of open file descriptors. """ @@ -2665,16 +2659,48 @@ def fd_count(): except FileNotFoundError: pass - count = 0 - for fd in range(MAXFD): + old_modes = None + if sys.platform == 'win32': + # bpo-25306, bpo-31009: Call CrtSetReportMode() to not kill the process + # on invalid file descriptor if Python is compiled in debug mode try: - # Prefer dup() over fstat(). fstat() can require input/output - # whereas dup() doesn't. - fd2 = os.dup(fd) - except OSError as e: - if e.errno != errno.EBADF: - raise + import msvcrt + msvcrt.CrtSetReportMode + except (AttributeError, ImportError): + # no msvcrt or a release build + pass else: - os.close(fd2) - count += 1 + old_modes = {} + for report_type in (msvcrt.CRT_WARN, + msvcrt.CRT_ERROR, + msvcrt.CRT_ASSERT): + old_modes[report_type] = msvcrt.CrtSetReportMode(report_type, 0) + + MAXFD = 256 + if hasattr(os, 'sysconf'): + try: + MAXFD = os.sysconf("SC_OPEN_MAX") + except OSError: + pass + + try: + count = 0 + for fd in range(MAXFD): + try: + # Prefer dup() over fstat(). fstat() can require input/output + # whereas dup() doesn't. + fd2 = os.dup(fd) + except OSError as e: + if e.errno != errno.EBADF: + raise + else: + os.close(fd2) + count += 1 + finally: + if old_modes is not None: + for report_type in (msvcrt.CRT_WARN, + msvcrt.CRT_ERROR, + msvcrt.CRT_ASSERT): + msvcrt.CrtSetReportMode(report_type, old_modes[report_type]) + return count diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index f63ed647f8..b756839748 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -835,22 +835,10 @@ class ArgsTestCase(BaseTestCase): import os import unittest - # Issue #25306: Disable popups and logs to stderr on assertion - # failures in MSCRT - try: - import msvcrt - msvcrt.CrtSetReportMode - except (ImportError, AttributeError): - # no Windows, o release build - pass - else: - for m in [msvcrt.CRT_WARN, msvcrt.CRT_ERROR, msvcrt.CRT_ASSERT]: - msvcrt.CrtSetReportMode(m, 0) - class FDLeakTest(unittest.TestCase): def test_leak(self): fd = os.open(__file__, os.O_RDONLY) - # bug: never cloes the file descriptor + # bug: never close the file descriptor """) self.check_leak(code, 'file descriptors')