diff -r 5f655369ef06 Lib/test/regrtest.py --- a/Lib/test/regrtest.py Mon Jan 28 13:27:02 2013 +0200 +++ b/Lib/test/regrtest.py Mon Jan 28 16:38:09 2013 -0600 @@ -1275,8 +1275,11 @@ # tests. If not, use normal unittest test loading. test_runner = getattr(the_module, "test_main", None) if test_runner is None: - tests = unittest.TestLoader().loadTestsFromModule(the_module) - test_runner = lambda: support.run_unittest(tests) + # Issue 16968: keeping an extra reference to the tests here + # can cause issues with garbage collection, particularly in + # threading._dangling + test_runner = lambda: support.run_unittest( + unittest.TestLoader().loadTestsFromModule(the_module)) test_runner() if huntrleaks: refleak = dash_R(the_module, test, test_runner, diff -r 5f655369ef06 Lib/test/support.py --- a/Lib/test/support.py Mon Jan 28 13:27:02 2013 +0200 +++ b/Lib/test/support.py Mon Jan 28 16:38:09 2013 -0600 @@ -1721,6 +1721,17 @@ except: break +class ReapedSuite(unittest.TestSuite): + """Use this class to wrap tests that should have threads and/or children + reaped. + """ + @reap_threads + def run(self, result): + try: + return super(unittest.TestSuite, self).run(result) + finally: + reap_children() + @contextlib.contextmanager def swap_attr(obj, attr, new_val): """Temporary swap out an attribute with a new object. diff -r 5f655369ef06 Lib/test/test_concurrent_futures.py --- a/Lib/test/test_concurrent_futures.py Mon Jan 28 13:27:02 2013 +0200 +++ b/Lib/test/test_concurrent_futures.py Mon Jan 28 16:38:09 2013 -0600 @@ -94,7 +94,7 @@ executor_type = futures.ProcessPoolExecutor -class ExecutorShutdownTest(unittest.TestCase): +class ExecutorShutdownTest: def test_run_after_shutdown(self): self.executor.shutdown() self.assertRaises(RuntimeError, @@ -122,7 +122,9 @@ f.result() -class ThreadPoolShutdownTest(ThreadPoolMixin, ExecutorShutdownTest): +class ThreadPoolShutdownTest(ThreadPoolMixin, + ExecutorShutdownTest, + unittest.TestCase): def _prime_executor(self): pass @@ -154,7 +156,9 @@ t.join() -class ProcessPoolShutdownTest(ProcessPoolMixin, ExecutorShutdownTest): +class ProcessPoolShutdownTest(ProcessPoolMixin, + ExecutorShutdownTest, + unittest.TestCase): def _prime_executor(self): pass @@ -190,8 +194,7 @@ p.join() -class WaitTests(unittest.TestCase): - +class WaitTests: def test_first_completed(self): future1 = self.executor.submit(mul, 21, 2) future2 = self.executor.submit(time.sleep, 1.5) @@ -291,8 +294,7 @@ self.assertEqual(set([future2]), pending) -class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests): - +class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests, unittest.TestCase): def test_pending_calls_race(self): # Issue #14406: multi-threaded race condition when waiting on all # futures. @@ -309,11 +311,11 @@ sys.setswitchinterval(oldswitchinterval) -class ProcessPoolWaitTests(ProcessPoolMixin, WaitTests): +class ProcessPoolWaitTests(ProcessPoolMixin, WaitTests, unittest.TestCase): pass -class AsCompletedTests(unittest.TestCase): +class AsCompletedTests: # TODO(brian@sweetapp.com): Should have a test with a non-zero timeout. def test_no_timeout(self): future1 = self.executor.submit(mul, 2, 21) @@ -351,15 +353,19 @@ completed_futures) -class ThreadPoolAsCompletedTests(ThreadPoolMixin, AsCompletedTests): +class ThreadPoolAsCompletedTests(ThreadPoolMixin, + AsCompletedTests, + unittest.TestCase): pass -class ProcessPoolAsCompletedTests(ProcessPoolMixin, AsCompletedTests): +class ProcessPoolAsCompletedTests(ProcessPoolMixin, + AsCompletedTests, + unittest.TestCase): pass -class ExecutorTest(unittest.TestCase): +class ExecutorTest: # Executor.shutdown() and context manager usage is tested by # ExecutorShutdownTest. def test_submit(self): @@ -419,7 +425,9 @@ "Stale reference not collected within timeout.") -class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest): +class ThreadPoolExecutorTest(ThreadPoolMixin, + ExecutorTest, + unittest.TestCase): def test_map_submits_without_iteration(self): """Tests verifying issue 11777.""" finished = [] @@ -431,7 +439,9 @@ self.assertCountEqual(finished, range(10)) -class ProcessPoolExecutorTest(ProcessPoolMixin, ExecutorTest): +class ProcessPoolExecutorTest(ProcessPoolMixin, + ExecutorTest, + unittest.TestCase): def test_killed_child(self): # When a child process is abruptly terminated, the whole pool gets # "broken". @@ -667,21 +677,8 @@ self.assertTrue(isinstance(f1.exception(timeout=5), OSError)) -@test.support.reap_threads -def test_main(): - try: - test.support.run_unittest(ProcessPoolExecutorTest, - ThreadPoolExecutorTest, - ProcessPoolWaitTests, - ThreadPoolWaitTests, - ProcessPoolAsCompletedTests, - ThreadPoolAsCompletedTests, - FutureTests, - ProcessPoolShutdownTest, - ThreadPoolShutdownTest, - ) - finally: - test.support.reap_children() +def load_tests(loader, tests, pattern): + return test.support.ReapedSuite(tests) if __name__ == "__main__": - test_main() + unittest.main()