Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 634aa68

Browse files
committed
Isolate the subprocess test_close_fds_when_max_fd_is_lowered test so
that the rlimit calls happens in a child process rather than the TestCase process to attempt to fix the gentoo buildbot's "Too many open files" error.
1 parent 92a4055 commit 634aa68

1 file changed

Lines changed: 30 additions & 8 deletions

File tree

Lib/test/test_subprocess.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,6 +1934,20 @@ def test_close_fds_when_max_fd_is_lowered(self):
19341934
"""Confirm that issue21618 is fixed (may fail under valgrind)."""
19351935
fd_status = support.findfile("fd_status.py", subdir="subprocessdata")
19361936

1937+
# This launches the meat of the test in a child process to
1938+
# avoid messing with the larger unittest processes maximum
1939+
# number of file descriptors.
1940+
# This process launches:
1941+
# +--> Process that lowers its RLIMIT_NOFILE aftr setting up
1942+
# a bunch of high open fds above the new lower rlimit.
1943+
# Those are reported via stdout before launching a new
1944+
# process with close_fds=False to run the actual test:
1945+
# +--> The TEST: This one launches a fd_status.py
1946+
# subprocess with close_fds=True so we can find out if
1947+
# any of the fds above the lowered rlimit are still open.
1948+
p = subprocess.Popen([sys.executable, '-c', textwrap.dedent(
1949+
'''
1950+
import os, resource, subprocess, sys, textwrap
19371951
open_fds = set()
19381952
# Add a bunch more fds to pass down.
19391953
for _ in range(40):
@@ -1949,12 +1963,15 @@ def test_close_fds_when_max_fd_is_lowered(self):
19491963
open_fds.remove(fd)
19501964
19511965
for fd in open_fds:
1952-
self.addCleanup(os.close, fd)
1966+
#self.addCleanup(os.close, fd)
19531967
os.set_inheritable(fd, True)
19541968
19551969
max_fd_open = max(open_fds)
19561970
1957-
import resource
1971+
# Communicate the open_fds to the parent unittest.TestCase process.
1972+
print(','.join(map(str, sorted(open_fds))))
1973+
sys.stdout.flush()
1974+
19581975
rlim_cur, rlim_max = resource.getrlimit(resource.RLIMIT_NOFILE)
19591976
try:
19601977
# 29 is lower than the highest fds we are leaving open.
@@ -1965,22 +1982,27 @@ def test_close_fds_when_max_fd_is_lowered(self):
19651982
# An explicit list of fds to check is passed to fd_status.py as
19661983
# letting fd_status rely on its default logic would miss the
19671984
# fds above rlim_cur as it normally only checks up to that limit.
1968-
p = subprocess.Popen(
1985+
subprocess.Popen(
19691986
[sys.executable, '-c',
19701987
textwrap.dedent("""
19711988
import subprocess, sys
1972-
subprocess.Popen([sys.executable, {fd_status!r}] +
1989+
subprocess.Popen([sys.executable, %r] +
19731990
[str(x) for x in range({max_fd})],
19741991
close_fds=True).wait()
1975-
""".format(fd_status=fd_status, max_fd=max_fd_open+1))],
1976-
stdout=subprocess.PIPE, close_fds=False)
1992+
""".format(max_fd=max_fd_open+1))],
1993+
close_fds=False).wait()
19771994
finally:
19781995
resource.setrlimit(resource.RLIMIT_NOFILE, (rlim_cur, rlim_max))
1996+
''' % fd_status)], stdout=subprocess.PIPE)
19791997

19801998
output, unused_stderr = p.communicate()
1981-
remaining_fds = set(map(int, output.strip().split(b',')))
1999+
output_lines = output.splitlines()
2000+
self.assertEqual(len(output_lines), 2,
2001+
msg="expected exactly two lines of output:\n%s" % output)
2002+
opened_fds = set(map(int, output_lines[0].strip().split(b',')))
2003+
remaining_fds = set(map(int, output_lines[1].strip().split(b',')))
19822004

1983-
self.assertFalse(remaining_fds & open_fds,
2005+
self.assertFalse(remaining_fds & opened_fds,
19842006
msg="Some fds were left open.")
19852007

19862008

0 commit comments

Comments
 (0)