@@ -2030,22 +2030,32 @@ def threading_cleanup(*original_values): |
|
|
2030 |
2030 |
global environment_altered |
2031 |
2031 |
|
2032 |
2032 |
_MAX_COUNT = 100 |
2033 |
|
- t0 = time.monotonic() |
|
2033 |
+ |
2034 |
2034 |
for count in range(_MAX_COUNT): |
2035 |
2035 |
values = _thread._count(), threading._dangling |
2036 |
2036 |
if values == original_values: |
2037 |
2037 |
break |
|
2038 |
+ |
|
2039 |
+if not count: |
|
2040 |
+# Display a warning at the first iteration |
|
2041 |
+environment_altered = True |
|
2042 |
+dangling_threads = values[1] |
|
2043 |
+print("Warning -- threading_cleanup() failed to cleanup " |
|
2044 |
+"%s threads (count: %s, dangling: %s)" |
|
2045 |
+% (values[0] - original_values[0], |
|
2046 |
+values[0], len(dangling_threads)), |
|
2047 |
+file=sys.stderr) |
|
2048 |
+for thread in dangling_threads: |
|
2049 |
+print(f"Dangling thread: {thread!r}", file=sys.stderr) |
|
2050 |
+sys.stderr.flush() |
|
2051 |
+ |
|
2052 |
+# Don't hold references to threads |
|
2053 |
+dangling_threads = None |
|
2054 |
+values = None |
|
2055 |
+ |
2038 |
2056 |
time.sleep(0.01) |
2039 |
2057 |
gc_collect() |
2040 |
|
-else: |
2041 |
|
-environment_altered = True |
2042 |
2058 |
|
2043 |
|
-dt = time.monotonic() - t0 |
2044 |
|
-print("Warning -- threading_cleanup() failed to cleanup %s threads " |
2045 |
|
-"after %.0f sec (count: %s, dangling: %s)" |
2046 |
|
-% (values[0] - original_values[0], dt, |
2047 |
|
-values[0], len(values[1])), |
2048 |
|
-file=sys.stderr) |
2049 |
2059 |
|
2050 |
2060 |
def reap_threads(func): |
2051 |
2061 |
"""Use this function when threads are being used. This will |