]> granicus.if.org Git - python/commitdiff
Isolate the subprocess test_close_fds_when_max_fd_is_lowered test so
authorGregory P. Smith <greg@krypto.org>
Mon, 16 Jun 2014 00:51:04 +0000 (17:51 -0700)
committerGregory P. Smith <greg@krypto.org>
Mon, 16 Jun 2014 00:51:04 +0000 (17:51 -0700)
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.

Lib/test/test_subprocess.py

index 720025a1178a5d95894154773202f20c99486d47..0c0535895828e7b0cd92c9bc5e454527c4c41596 100644 (file)
@@ -1934,6 +1934,20 @@ class POSIXProcessTestCase(BaseTestCase):
         """Confirm that issue21618 is fixed (may fail under valgrind)."""
         fd_status = support.findfile("fd_status.py", subdir="subprocessdata")
 
+        # This launches the meat of the test in a child process to
+        # avoid messing with the larger unittest processes maximum
+        # number of file descriptors.
+        #  This process launches:
+        #  +--> Process that lowers its RLIMIT_NOFILE aftr setting up
+        #    a bunch of high open fds above the new lower rlimit.
+        #    Those are reported via stdout before launching a new
+        #    process with close_fds=False to run the actual test:
+        #    +--> The TEST: This one launches a fd_status.py
+        #      subprocess with close_fds=True so we can find out if
+        #      any of the fds above the lowered rlimit are still open.
+        p = subprocess.Popen([sys.executable, '-c', textwrap.dedent(
+        '''
+        import os, resource, subprocess, sys, textwrap
         open_fds = set()
         # Add a bunch more fds to pass down.
         for _ in range(40):
@@ -1949,12 +1963,15 @@ class POSIXProcessTestCase(BaseTestCase):
             open_fds.remove(fd)
 
         for fd in open_fds:
-            self.addCleanup(os.close, fd)
+            #self.addCleanup(os.close, fd)
             os.set_inheritable(fd, True)
 
         max_fd_open = max(open_fds)
 
-        import resource
+        # Communicate the open_fds to the parent unittest.TestCase process.
+        print(','.join(map(str, sorted(open_fds))))
+        sys.stdout.flush()
+
         rlim_cur, rlim_max = resource.getrlimit(resource.RLIMIT_NOFILE)
         try:
             # 29 is lower than the highest fds we are leaving open.
@@ -1965,22 +1982,27 @@ class POSIXProcessTestCase(BaseTestCase):
             # An explicit list of fds to check is passed to fd_status.py as
             # letting fd_status rely on its default logic would miss the
             # fds above rlim_cur as it normally only checks up to that limit.
-            p = subprocess.Popen(
+            subprocess.Popen(
                 [sys.executable, '-c',
                  textwrap.dedent("""
                      import subprocess, sys
-                     subprocess.Popen([sys.executable, {fd_status!r}] +
+                     subprocess.Popen([sys.executable, %r] +
                                       [str(x) for x in range({max_fd})],
                                       close_fds=True).wait()
-                     """.format(fd_status=fd_status, max_fd=max_fd_open+1))],
-                stdout=subprocess.PIPE, close_fds=False)
+                     """.format(max_fd=max_fd_open+1))],
+                close_fds=False).wait()
         finally:
             resource.setrlimit(resource.RLIMIT_NOFILE, (rlim_cur, rlim_max))
+        ''' % fd_status)], stdout=subprocess.PIPE)
 
         output, unused_stderr = p.communicate()
-        remaining_fds = set(map(int, output.strip().split(b',')))
+        output_lines = output.splitlines()
+        self.assertEqual(len(output_lines), 2,
+                         msg="expected exactly two lines of output:\n%s" % output)
+        opened_fds = set(map(int, output_lines[0].strip().split(b',')))
+        remaining_fds = set(map(int, output_lines[1].strip().split(b',')))
 
-        self.assertFalse(remaining_fds & open_fds,
+        self.assertFalse(remaining_fds & opened_fds,
                          msg="Some fds were left open.")