summaryrefslogtreecommitdiffstats
path: root/Lib/test/support/threading_helper.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/support/threading_helper.py')
-rw-r--r--Lib/test/support/threading_helper.py53
1 files changed, 28 insertions, 25 deletions
diff --git a/Lib/test/support/threading_helper.py b/Lib/test/support/threading_helper.py
index 7f16050..afa25a7 100644
--- a/Lib/test/support/threading_helper.py
+++ b/Lib/test/support/threading_helper.py
@@ -22,34 +22,37 @@ from test import support
def threading_setup():
- return _thread._count(), threading._dangling.copy()
+ return _thread._count(), len(threading._dangling)
def threading_cleanup(*original_values):
- _MAX_COUNT = 100
-
- for count in range(_MAX_COUNT):
- values = _thread._count(), threading._dangling
- if values == original_values:
- break
-
- if not count:
- # Display a warning at the first iteration
- support.environment_altered = True
- dangling_threads = values[1]
- support.print_warning(f"threading_cleanup() failed to cleanup "
- f"{values[0] - original_values[0]} threads "
- f"(count: {values[0]}, "
- f"dangling: {len(dangling_threads)})")
- for thread in dangling_threads:
- support.print_warning(f"Dangling thread: {thread!r}")
-
- # Don't hold references to threads
- dangling_threads = None
- values = None
-
- time.sleep(0.01)
- support.gc_collect()
+ orig_count, orig_ndangling = original_values
+
+ timeout = 1.0
+ for _ in support.sleeping_retry(timeout, error=False):
+ # Copy the thread list to get a consistent output. threading._dangling
+ # is a WeakSet, its value changes when it's read.
+ dangling_threads = list(threading._dangling)
+ count = _thread._count()
+
+ if count <= orig_count:
+ return
+
+ # Timeout!
+ support.environment_altered = True
+ support.print_warning(
+ f"threading_cleanup() failed to clean up threads "
+ f"in {timeout:.1f} seconds\n"
+ f" before: thread count={orig_count}, dangling={orig_ndangling}\n"
+ f" after: thread count={count}, dangling={len(dangling_threads)}")
+ for thread in dangling_threads:
+ support.print_warning(f"Dangling thread: {thread!r}")
+
+ # The warning happens when a test spawns threads and some of these threads
+ # are still running after the test completes. To fix this warning, join
+ # threads explicitly to wait until they complete.
+ #
+ # To make the warning more likely, reduce the timeout.
def reap_threads(func):