Skip to content

Commit 302bbbe

Browse files
authored
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
1 parent 90addd6 commit 302bbbe

File tree

2 files changed

+43
-29
lines changed

2 files changed

+43
-29
lines changed

Lib/test/support/__init__.py

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2649,12 +2649,6 @@ def disable_faulthandler():
26492649
faulthandler.enable(file=fd, all_threads=True)
26502650

26512651

2652-
try:
2653-
MAXFD = os.sysconf("SC_OPEN_MAX")
2654-
except Exception:
2655-
MAXFD = 256
2656-
2657-
26582652
def fd_count():
26592653
"""Count the number of open file descriptors.
26602654
"""
@@ -2665,16 +2659,48 @@ def fd_count():
26652659
except FileNotFoundError:
26662660
pass
26672661

2668-
count = 0
2669-
for fd in range(MAXFD):
2662+
old_modes = None
2663+
if sys.platform == 'win32':
2664+
# bpo-25306, bpo-31009: Call CrtSetReportMode() to not kill the process
2665+
# on invalid file descriptor if Python is compiled in debug mode
26702666
try:
2671-
# Prefer dup() over fstat(). fstat() can require input/output
2672-
# whereas dup() doesn't.
2673-
fd2 = os.dup(fd)
2674-
except OSError as e:
2675-
if e.errno != errno.EBADF:
2676-
raise
2667+
import msvcrt
2668+
msvcrt.CrtSetReportMode
2669+
except (AttributeError, ImportError):
2670+
# no msvcrt or a release build
2671+
pass
26772672
else:
2678-
os.close(fd2)
2679-
count += 1
2673+
old_modes = {}
2674+
for report_type in (msvcrt.CRT_WARN,
2675+
msvcrt.CRT_ERROR,
2676+
msvcrt.CRT_ASSERT):
2677+
old_modes[report_type] = msvcrt.CrtSetReportMode(report_type, 0)
2678+
2679+
MAXFD = 256
2680+
if hasattr(os, 'sysconf'):
2681+
try:
2682+
MAXFD = os.sysconf("SC_OPEN_MAX")
2683+
except OSError:
2684+
pass
2685+
2686+
try:
2687+
count = 0
2688+
for fd in range(MAXFD):
2689+
try:
2690+
# Prefer dup() over fstat(). fstat() can require input/output
2691+
# whereas dup() doesn't.
2692+
fd2 = os.dup(fd)
2693+
except OSError as e:
2694+
if e.errno != errno.EBADF:
2695+
raise
2696+
else:
2697+
os.close(fd2)
2698+
count += 1
2699+
finally:
2700+
if old_modes is not None:
2701+
for report_type in (msvcrt.CRT_WARN,
2702+
msvcrt.CRT_ERROR,
2703+
msvcrt.CRT_ASSERT):
2704+
msvcrt.CrtSetReportMode(report_type, old_modes[report_type])
2705+
26802706
return count

Lib/test/test_regrtest.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -835,22 +835,10 @@ def test_huntrleaks_fd_leak(self):
835835
import os
836836
import unittest
837837
838-
# Issue #25306: Disable popups and logs to stderr on assertion
839-
# failures in MSCRT
840-
try:
841-
import msvcrt
842-
msvcrt.CrtSetReportMode
843-
except (ImportError, AttributeError):
844-
# no Windows, o release build
845-
pass
846-
else:
847-
for m in [msvcrt.CRT_WARN, msvcrt.CRT_ERROR, msvcrt.CRT_ASSERT]:
848-
msvcrt.CrtSetReportMode(m, 0)
849-
850838
class FDLeakTest(unittest.TestCase):
851839
def test_leak(self):
852840
fd = os.open(__file__, os.O_RDONLY)
853-
# bug: never cloes the file descriptor
841+
# bug: never close the file descriptor
854842
""")
855843
self.check_leak(code, 'file descriptors')
856844

0 commit comments

Comments
 (0)