@@ -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