diff -r de08a90ec660 Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py Sat Mar 28 20:39:51 2015 +0200 +++ b/Lib/test/support/__init__.py Sat Mar 28 21:56:33 2015 +0200 @@ -1942,6 +1942,18 @@ def reap_children(): break @contextlib.contextmanager +def start_threads(threads, unlock=None): + with contextlib.ExitStack() as stack: + try: + for t in threads: + t.start() + stack.callback(t.join) + yield + finally: + if unlock: + unlock() + +@contextlib.contextmanager def swap_attr(obj, attr, new_val): """Temporary swap out an attribute with a new object. diff -r de08a90ec660 Lib/test/test_bz2.py --- a/Lib/test/test_bz2.py Sat Mar 28 20:39:51 2015 +0200 +++ b/Lib/test/test_bz2.py Sat Mar 28 21:56:33 2015 +0200 @@ -507,10 +507,8 @@ class BZ2FileTest(BaseTest): for i in range(5): f.write(data) threads = [threading.Thread(target=comp) for i in range(nthreads)] - for t in threads: - t.start() - for t in threads: - t.join() + with support.start_threads(threads): + pass def testWithoutThreading(self): module = support.import_fresh_module("bz2", blocked=("threading",)) diff -r de08a90ec660 Lib/test/test_capi.py --- a/Lib/test/test_capi.py Sat Mar 28 20:39:51 2015 +0200 +++ b/Lib/test/test_capi.py Sat Mar 28 21:56:33 2015 +0200 @@ -284,15 +284,11 @@ class TestPendingCalls(unittest.TestCase context.lock = threading.Lock() context.event = threading.Event() - for i in range(context.nThreads): - t = threading.Thread(target=self.pendingcalls_thread, args = (context,)) - t.start() - threads.append(t) - - self.pendingcalls_wait(context.l, n, context) - - for t in threads: - t.join() + threads = [threading.Thread(target=self.pendingcalls_thread, + args=(context,)) + for i in range(context.nThreads)] + with support.start_threads(threads): + self.pendingcalls_wait(context.l, n, context) def pendingcalls_thread(self, context): try: diff -r de08a90ec660 Lib/test/test_gc.py --- a/Lib/test/test_gc.py Sat Mar 28 20:39:51 2015 +0200 +++ b/Lib/test/test_gc.py Sat Mar 28 21:56:33 2015 +0200 @@ -1,6 +1,6 @@ import unittest from test.support import (verbose, refcount_test, run_unittest, - strip_python_stderr, cpython_only) + strip_python_stderr, cpython_only, start_threads) from test.script_helper import assert_python_ok, make_script, temp_dir import sys @@ -397,19 +397,13 @@ class GCTests(unittest.TestCase): old_switchinterval = sys.getswitchinterval() sys.setswitchinterval(1e-5) try: - exit = False + exit = [] threads = [] for i in range(N_THREADS): t = threading.Thread(target=run_thread) threads.append(t) - try: - for t in threads: - t.start() - finally: + with start_threads(threads, lambda: exit.append(1)): time.sleep(1.0) - exit = True - for t in threads: - t.join() finally: sys.setswitchinterval(old_switchinterval) gc.collect() diff -r de08a90ec660 Lib/test/test_io.py --- a/Lib/test/test_io.py Sat Mar 28 20:39:51 2015 +0200 +++ b/Lib/test/test_io.py Sat Mar 28 21:56:33 2015 +0200 @@ -1131,11 +1131,8 @@ class BufferedReaderTest(unittest.TestCa errors.append(e) raise threads = [threading.Thread(target=f) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) # yield - for t in threads: - t.join() + with support.start_threads(threads): + time.sleep(0.02) # yield self.assertFalse(errors, "the following exceptions were caught: %r" % errors) s = b''.join(results) @@ -1454,11 +1451,8 @@ class BufferedWriterTest(unittest.TestCa errors.append(e) raise threads = [threading.Thread(target=f) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) # yield - for t in threads: - t.join() + with support.start_threads(threads): + time.sleep(0.02) # yield self.assertFalse(errors, "the following exceptions were caught: %r" % errors) bufio.close() @@ -2752,14 +2746,10 @@ class TextIOWrapperTest(unittest.TestCas text = "Thread%03d\n" % n event.wait() f.write(text) - threads = [threading.Thread(target=lambda n=x: run(n)) + threads = [threading.Thread(target=run, args=(x,)) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) - event.set() - for t in threads: - t.join() + with support.start_threads(threads, event.set): + time.sleep(0.02) with self.open(support.TESTFN) as f: content = f.read() for n in range(20): @@ -3493,7 +3483,7 @@ class SignalsTest(unittest.TestCase): self.assertRaises(ZeroDivisionError, wio.write, large_data) finally: signal.alarm(0) - t.join() + t.join() # We got one byte, get another one and check that it isn't a # repeat of the first one. read_results.append(os.read(r, 1)) diff -r de08a90ec660 Lib/test/test_threaded_import.py --- a/Lib/test/test_threaded_import.py Sat Mar 28 20:39:51 2015 +0200 +++ b/Lib/test/test_threaded_import.py Sat Mar 28 21:56:33 2015 +0200 @@ -14,7 +14,7 @@ import shutil import unittest from test.support import ( verbose, import_module, run_unittest, TESTFN, reap_threads, - forget, unlink, rmtree) + forget, unlink, rmtree, start_threads) threading = import_module('threading') def task(N, done, done_tasks, errors): @@ -116,11 +116,10 @@ class ThreadedImportTests(unittest.TestC done_tasks = [] done.clear() t0 = time.monotonic() - for i in range(N): - t = threading.Thread(target=task, - args=(N, done, done_tasks, errors,)) - t.start() - completed = done.wait(10 * 60) + with start_threads(threading.Thread(target=task, + args=(N, done, done_tasks, errors,)) + for i in range(N)): + completed = done.wait(10 * 60) dt = time.monotonic() - t0 if verbose: print("%.1f ms" % (dt*1e3), flush=True, end=" ") diff -r de08a90ec660 Lib/test/test_threadedtempfile.py --- a/Lib/test/test_threadedtempfile.py Sat Mar 28 20:39:51 2015 +0200 +++ b/Lib/test/test_threadedtempfile.py Sat Mar 28 21:56:33 2015 +0200 @@ -49,20 +49,21 @@ class ThreadedTempFileTest(unittest.Test threads = [] thread_info = threading_setup() - for i in range(NUM_THREADS): - t = TempFileGreedy() - threads.append(t) - t.start() + try: + for i in range(NUM_THREADS): + t = TempFileGreedy() + t.start() + threads.append(t) + finally: + startEvent.set() - startEvent.set() - - ok = 0 - errors = [] - for t in threads: - t.join() - ok += t.ok_count - if t.error_count: - errors.append(str(t.name) + str(t.errors.getvalue())) + ok = 0 + errors = [] + for t in threads: + t.join() + ok += t.ok_count + if t.error_count: + errors.append(str(t.name) + str(t.errors.getvalue())) threading_cleanup(*thread_info) diff -r de08a90ec660 Lib/test/test_threading_local.py --- a/Lib/test/test_threading_local.py Sat Mar 28 20:39:51 2015 +0200 +++ b/Lib/test/test_threading_local.py Sat Mar 28 21:56:33 2015 +0200 @@ -64,14 +64,9 @@ class BaseLocalTest: # Simply check that the variable is correctly set self.assertEqual(local.x, i) - threads= [] - for i in range(10): - t = threading.Thread(target=f, args=(i,)) - t.start() - threads.append(t) - - for t in threads: - t.join() + with support.start_threads(threading.Thread(target=f, args=(i,)) + for i in range(10)): + pass def test_derived_cycle_dealloc(self): # http://bugs.python.org/issue6990