]> granicus.if.org Git - python/commitdiff
[3.6] bpo-31234: Join threads in tests (#3589)
authorVictor Stinner <victor.stinner@gmail.com>
Fri, 15 Sep 2017 23:55:47 +0000 (16:55 -0700)
committerGitHub <noreply@github.com>
Fri, 15 Sep 2017 23:55:47 +0000 (16:55 -0700)
* bpo-31234: Join threads in tests (#3572)

Call thread.join() on threads to prevent the "dangling threads"
warning.

(cherry picked from commit 18e95b4176256f100429a806d0455406df98f984)

* 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 8dcf22f442320e4c1a5408e67b4c9002ad105f17)

* bpo-31234: Join threads in test_threading (#3579)

Call thread.join() to prevent the "dangling thread" warning.

(cherry picked from commit b8c7be2c523b012e57915182543d06657161057f)

* bpo-31234: Join threads in test_queue (#3586)

Call thread.join() to prevent the "dangling thread" warning.

(cherry picked from commit 167cbde50a88ec2a7d26b2cb9891d5e32bdfbfb5)

* 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 da3e5cf961f9bcc4bb376386cfe7a2865325086c)

Lib/test/test_concurrent_futures.py
Lib/test/test_decimal.py
Lib/test/test_hashlib.py
Lib/test/test_queue.py
Lib/test/test_smtplib.py
Lib/test/test_threading.py
Lib/test/test_xmlrpc.py

index e5d6b7e09b55007fdb30d650d99bdcad2baa0363..667878429fc2b3e1464204a2b5a9b2582a5c9ac5 100644 (file)
@@ -776,6 +776,7 @@ class FutureTests(BaseTestCase):
         t.start()
 
         self.assertEqual(f1.result(timeout=5), 42)
+        t.join()
 
     def test_result_with_cancel(self):
         # TODO(brian@sweetapp.com): This test is timing dependent.
@@ -789,6 +790,7 @@ class FutureTests(BaseTestCase):
         t.start()
 
         self.assertRaises(futures.CancelledError, f1.result, timeout=5)
+        t.join()
 
     def test_exception_with_timeout(self):
         self.assertRaises(futures.TimeoutError,
@@ -817,6 +819,7 @@ class FutureTests(BaseTestCase):
         t.start()
 
         self.assertTrue(isinstance(f1.exception(timeout=5), OSError))
+        t.join()
 
 @test.support.reap_threads
 def test_main():
index 617a37eec8223aadfcaeefa617bdd02f00a62872..57094ad6695262f7774a2e18be2d3d2db1e01500 100644 (file)
@@ -1614,6 +1614,9 @@ class ThreadingTest(unittest.TestCase):
         for sig in Signals[self.decimal]:
             self.assertFalse(DefaultContext.flags[sig])
 
+        th1.join()
+        th2.join()
+
         DefaultContext.prec = save_prec
         DefaultContext.Emax = save_emax
         DefaultContext.Emin = save_emin
index f748b461907f6fb977ff9306cb09a346a41eaa24..647719ea62ce1a136743dea1f39a88b0032d1afc 100644 (file)
@@ -750,28 +750,28 @@ class HashLibTestCase(unittest.TestCase):
         hasher = hashlib.sha1()
         num_threads = 5
         smallest_data = b'swineflu'
-        data = smallest_data*200000
+        data = smallest_data * 200000
         expected_hash = hashlib.sha1(data*num_threads).hexdigest()
 
-        def hash_in_chunks(chunk_size, event):
+        def hash_in_chunks(chunk_size):
             index = 0
             while index < len(data):
-                hasher.update(data[index:index+chunk_size])
+                hasher.update(data[index:index + chunk_size])
                 index += chunk_size
-            event.set()
 
-        events = []
+        threads = []
         for threadnum in range(num_threads):
-            chunk_size = len(data) // (10**threadnum)
+            chunk_size = len(data) // (10 ** threadnum)
             self.assertGreater(chunk_size, 0)
             self.assertEqual(chunk_size % len(smallest_data), 0)
-            event = threading.Event()
-            events.append(event)
-            threading.Thread(target=hash_in_chunks,
-                             args=(chunk_size, event)).start()
-
-        for event in events:
-            event.wait()
+            thread = threading.Thread(target=hash_in_chunks,
+                                      args=(chunk_size,))
+            threads.append(thread)
+
+        for thread in threads:
+            thread.start()
+        for thread in threads:
+            thread.join()
 
         self.assertEqual(expected_hash, hasher.hexdigest())
 
index 4ccaa39adff69fdf5fcf189486a6117e555ca13d..c6860958dda6c37fecf88c33bcfcccb92cca19cb 100644 (file)
@@ -46,28 +46,27 @@ class _TriggerThread(threading.Thread):
 
 class BlockingTestMixin:
 
-    def tearDown(self):
-        self.t = None
-
     def do_blocking_test(self, block_func, block_args, trigger_func, trigger_args):
-        self.t = _TriggerThread(trigger_func, trigger_args)
-        self.t.start()
-        self.result = block_func(*block_args)
-        # If block_func returned before our thread made the call, we failed!
-        if not self.t.startedEvent.is_set():
-            self.fail("blocking function '%r' appeared not to block" %
-                      block_func)
-        self.t.join(10) # make sure the thread terminates
-        if self.t.is_alive():
-            self.fail("trigger function '%r' appeared to not return" %
-                      trigger_func)
-        return self.result
+        thread = _TriggerThread(trigger_func, trigger_args)
+        thread.start()
+        try:
+            self.result = block_func(*block_args)
+            # If block_func returned before our thread made the call, we failed!
+            if not thread.startedEvent.is_set():
+                self.fail("blocking function '%r' appeared not to block" %
+                          block_func)
+            return self.result
+        finally:
+            thread.join(10) # make sure the thread terminates
+            if thread.is_alive():
+                self.fail("trigger function '%r' appeared to not return" %
+                          trigger_func)
 
     # Call this instead if block_func is supposed to raise an exception.
     def do_exceptional_blocking_test(self,block_func, block_args, trigger_func,
                                    trigger_args, expected_exception_class):
-        self.t = _TriggerThread(trigger_func, trigger_args)
-        self.t.start()
+        thread = _TriggerThread(trigger_func, trigger_args)
+        thread.start()
         try:
             try:
                 block_func(*block_args)
@@ -77,11 +76,11 @@ class BlockingTestMixin:
                 self.fail("expected exception of kind %r" %
                                  expected_exception_class)
         finally:
-            self.t.join(10) # make sure the thread terminates
-            if self.t.is_alive():
+            thread.join(10) # make sure the thread terminates
+            if thread.is_alive():
                 self.fail("trigger function '%r' appeared to not return" %
                                  trigger_func)
-            if not self.t.startedEvent.is_set():
+            if not thread.startedEvent.is_set():
                 self.fail("trigger thread ended but event never set")
 
 
@@ -159,8 +158,11 @@ class BaseQueueTestMixin(BlockingTestMixin):
 
     def queue_join_test(self, q):
         self.cum = 0
+        threads = []
         for i in (0,1):
-            threading.Thread(target=self.worker, args=(q,)).start()
+            thread = threading.Thread(target=self.worker, args=(q,))
+            thread.start()
+            threads.append(thread)
         for i in range(100):
             q.put(i)
         q.join()
@@ -169,6 +171,8 @@ class BaseQueueTestMixin(BlockingTestMixin):
         for i in (0,1):
             q.put(-1)         # instruct the threads to close
         q.join()                # verify that you can join twice
+        for thread in threads:
+            thread.join()
 
     def test_queue_task_done(self):
         # Test to make sure a queue task completed successfully.
index 28539f360f5974ec2d65e0782d980b74a57d73af..dd3a6eeca69c3411bff11db2572105bbe8d97823 100644 (file)
@@ -604,7 +604,9 @@ class TooLongLineTests(unittest.TestCase):
         self.sock.settimeout(15)
         self.port = support.bind_port(self.sock)
         servargs = (self.evt, self.respdata, self.sock)
-        threading.Thread(target=server, args=servargs).start()
+        thread = threading.Thread(target=server, args=servargs)
+        thread.start()
+        self.addCleanup(thread.join)
         self.evt.wait()
         self.evt.clear()
 
index 162a72ea03f0b286d8a1ee4aa99671b96d97620c..9cadc0f1c025a912e90c02f6febcad75b88d4bd6 100644 (file)
@@ -575,6 +575,7 @@ class ThreadTests(BaseTestCase):
         self.assertFalse(t.is_alive())
         # And verify the thread disposed of _tstate_lock.
         self.assertIsNone(t._tstate_lock)
+        t.join()
 
     def test_repr_stopped(self):
         # Verify that "stopped" shows up in repr(Thread) appropriately.
@@ -601,6 +602,7 @@ class ThreadTests(BaseTestCase):
                 break
             time.sleep(0.01)
         self.assertIn(LOOKING_FOR, repr(t)) # we waited at least 5 seconds
+        t.join()
 
     def test_BoundedSemaphore_limit(self):
         # BoundedSemaphore should raise ValueError if released too often.
@@ -915,6 +917,7 @@ class ThreadingExceptionTests(BaseTestCase):
         thread = threading.Thread()
         thread.start()
         self.assertRaises(RuntimeError, thread.start)
+        thread.join()
 
     def test_joining_current_thread(self):
         current_thread = threading.current_thread()
@@ -928,6 +931,7 @@ class ThreadingExceptionTests(BaseTestCase):
         thread = threading.Thread()
         thread.start()
         self.assertRaises(RuntimeError, setattr, thread, "daemon", True)
+        thread.join()
 
     def test_releasing_unacquired_lock(self):
         lock = threading.Lock()
@@ -1090,6 +1094,8 @@ class TimerTests(BaseTestCase):
         self.callback_event.wait()
         self.assertEqual(len(self.callback_args), 2)
         self.assertEqual(self.callback_args, [((), {}), ((), {})])
+        timer1.join()
+        timer2.join()
 
     def _callback_spy(self, *args, **kwargs):
         self.callback_args.append((args[:], kwargs.copy()))
index e98a3a7160fea0b8d8581f0755f254b22a9a9659..f9bf304010e1c780bcbf448bb84dfc51f47d7679 100644 (file)
@@ -759,7 +759,9 @@ class BaseServerTestCase(unittest.TestCase):
         self.evt = threading.Event()
         # start server thread to handle requests
         serv_args = (self.evt, self.request_count, self.requestHandler)
-        threading.Thread(target=self.threadFunc, args=serv_args).start()
+        thread = threading.Thread(target=self.threadFunc, args=serv_args)
+        thread.start()
+        self.addCleanup(thread.join)
 
         # wait for the server to be ready
         self.evt.wait()
@@ -1211,7 +1213,9 @@ class FailingServerTestCase(unittest.TestCase):
         self.evt = threading.Event()
         # start server thread to handle requests
         serv_args = (self.evt, 1)
-        threading.Thread(target=http_server, args=serv_args).start()
+        thread = threading.Thread(target=http_server, args=serv_args)
+        thread.start()
+        self.addCleanup(thread.join)
 
         # wait for the server to be ready
         self.evt.wait()