Skip to content

Commit 2c1c2ca

Browse files
authored
[3.6] bpo-31234: Join threads in tests (#3589)
* bpo-31234: Join threads in tests (#3572) Call thread.join() on threads to prevent the "dangling threads" warning. (cherry picked from commit 18e95b4) * bpo-31234: Join threads in test_hashlib (#3573) * bpo-31234: Join threads in test_hashlib Use thread.join() to wait until the parallel hash tasks complete rather than using events. Calling thread.join() prevent "dangling thread" warnings. * test_hashlib: minor PEP 8 coding style fixes (cherry picked from commit 8dcf22f) * bpo-31234: Join threads in test_threading (#3579) Call thread.join() to prevent the "dangling thread" warning. (cherry picked from commit b8c7be2) * bpo-31234: Join threads in test_queue (#3586) Call thread.join() to prevent the "dangling thread" warning. (cherry picked from commit 167cbde) * bpo-31234: Join timers in test_threading (#3598) Call the .join() method of threading.Timer timers to prevent the "threading_cleanup() failed to cleanup 1 threads" warning. (cherry picked from commit da3e5cf)
1 parent 4d72945 commit 2c1c2ca

File tree

7 files changed

+59
-37
lines changed

7 files changed

+59
-37
lines changed

Lib/test/test_concurrent_futures.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,7 @@ def notification():
776776
t.start()
777777

778778
self.assertEqual(f1.result(timeout=5), 42)
779+
t.join()
779780

780781
def test_result_with_cancel(self):
781782
# TODO([email protected]): This test is timing dependent.
@@ -789,6 +790,7 @@ def notification():
789790
t.start()
790791

791792
self.assertRaises(futures.CancelledError, f1.result, timeout=5)
793+
t.join()
792794

793795
def test_exception_with_timeout(self):
794796
self.assertRaises(futures.TimeoutError,
@@ -817,6 +819,7 @@ def notification():
817819
t.start()
818820

819821
self.assertTrue(isinstance(f1.exception(timeout=5), OSError))
822+
t.join()
820823

821824
@test.support.reap_threads
822825
def test_main():

Lib/test/test_decimal.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,6 +1614,9 @@ def test_threading(self):
16141614
for sig in Signals[self.decimal]:
16151615
self.assertFalse(DefaultContext.flags[sig])
16161616

1617+
th1.join()
1618+
th2.join()
1619+
16171620
DefaultContext.prec = save_prec
16181621
DefaultContext.Emax = save_emax
16191622
DefaultContext.Emin = save_emin

Lib/test/test_hashlib.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -750,28 +750,28 @@ def test_threaded_hashing(self):
750750
hasher = hashlib.sha1()
751751
num_threads = 5
752752
smallest_data = b'swineflu'
753-
data = smallest_data*200000
753+
data = smallest_data * 200000
754754
expected_hash = hashlib.sha1(data*num_threads).hexdigest()
755755

756-
def hash_in_chunks(chunk_size, event):
756+
def hash_in_chunks(chunk_size):
757757
index = 0
758758
while index < len(data):
759-
hasher.update(data[index:index+chunk_size])
759+
hasher.update(data[index:index + chunk_size])
760760
index += chunk_size
761-
event.set()
762761

763-
events = []
762+
threads = []
764763
for threadnum in range(num_threads):
765-
chunk_size = len(data) // (10**threadnum)
764+
chunk_size = len(data) // (10 ** threadnum)
766765
self.assertGreater(chunk_size, 0)
767766
self.assertEqual(chunk_size % len(smallest_data), 0)
768-
event = threading.Event()
769-
events.append(event)
770-
threading.Thread(target=hash_in_chunks,
771-
args=(chunk_size, event)).start()
772-
773-
for event in events:
774-
event.wait()
767+
thread = threading.Thread(target=hash_in_chunks,
768+
args=(chunk_size,))
769+
threads.append(thread)
770+
771+
for thread in threads:
772+
thread.start()
773+
for thread in threads:
774+
thread.join()
775775

776776
self.assertEqual(expected_hash, hasher.hexdigest())
777777

Lib/test/test_queue.py

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,28 +46,27 @@ def run(self):
4646

4747
class BlockingTestMixin:
4848

49-
def tearDown(self):
50-
self.t = None
51-
5249
def do_blocking_test(self, block_func, block_args, trigger_func, trigger_args):
53-
self.t = _TriggerThread(trigger_func, trigger_args)
54-
self.t.start()
55-
self.result = block_func(*block_args)
56-
# If block_func returned before our thread made the call, we failed!
57-
if not self.t.startedEvent.is_set():
58-
self.fail("blocking function '%r' appeared not to block" %
59-
block_func)
60-
self.t.join(10) # make sure the thread terminates
61-
if self.t.is_alive():
62-
self.fail("trigger function '%r' appeared to not return" %
63-
trigger_func)
64-
return self.result
50+
thread = _TriggerThread(trigger_func, trigger_args)
51+
thread.start()
52+
try:
53+
self.result = block_func(*block_args)
54+
# If block_func returned before our thread made the call, we failed!
55+
if not thread.startedEvent.is_set():
56+
self.fail("blocking function '%r' appeared not to block" %
57+
block_func)
58+
return self.result
59+
finally:
60+
thread.join(10) # make sure the thread terminates
61+
if thread.is_alive():
62+
self.fail("trigger function '%r' appeared to not return" %
63+
trigger_func)
6564

6665
# Call this instead if block_func is supposed to raise an exception.
6766
def do_exceptional_blocking_test(self,block_func, block_args, trigger_func,
6867
trigger_args, expected_exception_class):
69-
self.t = _TriggerThread(trigger_func, trigger_args)
70-
self.t.start()
68+
thread = _TriggerThread(trigger_func, trigger_args)
69+
thread.start()
7170
try:
7271
try:
7372
block_func(*block_args)
@@ -77,11 +76,11 @@ def do_exceptional_blocking_test(self,block_func, block_args, trigger_func,
7776
self.fail("expected exception of kind %r" %
7877
expected_exception_class)
7978
finally:
80-
self.t.join(10) # make sure the thread terminates
81-
if self.t.is_alive():
79+
thread.join(10) # make sure the thread terminates
80+
if thread.is_alive():
8281
self.fail("trigger function '%r' appeared to not return" %
8382
trigger_func)
84-
if not self.t.startedEvent.is_set():
83+
if not thread.startedEvent.is_set():
8584
self.fail("trigger thread ended but event never set")
8685

8786

@@ -159,8 +158,11 @@ def worker(self, q):
159158

160159
def queue_join_test(self, q):
161160
self.cum = 0
161+
threads = []
162162
for i in (0,1):
163-
threading.Thread(target=self.worker, args=(q,)).start()
163+
thread = threading.Thread(target=self.worker, args=(q,))
164+
thread.start()
165+
threads.append(thread)
164166
for i in range(100):
165167
q.put(i)
166168
q.join()
@@ -169,6 +171,8 @@ def queue_join_test(self, q):
169171
for i in (0,1):
170172
q.put(-1) # instruct the threads to close
171173
q.join() # verify that you can join twice
174+
for thread in threads:
175+
thread.join()
172176

173177
def test_queue_task_done(self):
174178
# Test to make sure a queue task completed successfully.

Lib/test/test_smtplib.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,9 @@ def setUp(self):
604604
self.sock.settimeout(15)
605605
self.port = support.bind_port(self.sock)
606606
servargs = (self.evt, self.respdata, self.sock)
607-
threading.Thread(target=server, args=servargs).start()
607+
thread = threading.Thread(target=server, args=servargs)
608+
thread.start()
609+
self.addCleanup(thread.join)
608610
self.evt.wait()
609611
self.evt.clear()
610612

Lib/test/test_threading.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ def f():
575575
self.assertFalse(t.is_alive())
576576
# And verify the thread disposed of _tstate_lock.
577577
self.assertIsNone(t._tstate_lock)
578+
t.join()
578579

579580
def test_repr_stopped(self):
580581
# Verify that "stopped" shows up in repr(Thread) appropriately.
@@ -601,6 +602,7 @@ def f():
601602
break
602603
time.sleep(0.01)
603604
self.assertIn(LOOKING_FOR, repr(t)) # we waited at least 5 seconds
605+
t.join()
604606

605607
def test_BoundedSemaphore_limit(self):
606608
# BoundedSemaphore should raise ValueError if released too often.
@@ -915,6 +917,7 @@ def test_start_thread_again(self):
915917
thread = threading.Thread()
916918
thread.start()
917919
self.assertRaises(RuntimeError, thread.start)
920+
thread.join()
918921

919922
def test_joining_current_thread(self):
920923
current_thread = threading.current_thread()
@@ -928,6 +931,7 @@ def test_daemonize_active_thread(self):
928931
thread = threading.Thread()
929932
thread.start()
930933
self.assertRaises(RuntimeError, setattr, thread, "daemon", True)
934+
thread.join()
931935

932936
def test_releasing_unacquired_lock(self):
933937
lock = threading.Lock()
@@ -1090,6 +1094,8 @@ def test_init_immutable_default_args(self):
10901094
self.callback_event.wait()
10911095
self.assertEqual(len(self.callback_args), 2)
10921096
self.assertEqual(self.callback_args, [((), {}), ((), {})])
1097+
timer1.join()
1098+
timer2.join()
10931099

10941100
def _callback_spy(self, *args, **kwargs):
10951101
self.callback_args.append((args[:], kwargs.copy()))

Lib/test/test_xmlrpc.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,9 @@ def setUp(self):
759759
self.evt = threading.Event()
760760
# start server thread to handle requests
761761
serv_args = (self.evt, self.request_count, self.requestHandler)
762-
threading.Thread(target=self.threadFunc, args=serv_args).start()
762+
thread = threading.Thread(target=self.threadFunc, args=serv_args)
763+
thread.start()
764+
self.addCleanup(thread.join)
763765

764766
# wait for the server to be ready
765767
self.evt.wait()
@@ -1211,7 +1213,9 @@ def setUp(self):
12111213
self.evt = threading.Event()
12121214
# start server thread to handle requests
12131215
serv_args = (self.evt, 1)
1214-
threading.Thread(target=http_server, args=serv_args).start()
1216+
thread = threading.Thread(target=http_server, args=serv_args)
1217+
thread.start()
1218+
self.addCleanup(thread.join)
12151219

12161220
# wait for the server to be ready
12171221
self.evt.wait()

0 commit comments

Comments
 (0)