@@ -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 |
|