From 15e2bc2b83342df0eb21a2f12f0b35411c76c226 Mon Sep 17 00:00:00 2001 From: Ramses Rodenburg Date: Fri, 4 Sep 2026 12:43:47 +0200 Subject: [PATCH] fix: prevent worker threads from blocking forever on an empty queue process_host() guards its loop with host_queue.qsize() and then performs a blocking host_queue.get(). With --threads N, several workers can pass the qsize() check while a single item remains: one wins the get(), the others block in it forever. Every queued item still gets its task_done(), so work_queue.join() returns and main() runs to completion - the scan finishes and the results are written. But the leaked workers are non-daemon threads, so threading._shutdown() joins them forever at interpreter exit and the process never terminates. Use a non-blocking get(), which makes the existing "except queue.Empty: break" reachable. The sibling loops in this file, remove_from_queue() and process_output(), already read their queues with block=False. --- analyze_hosts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyze_hosts.py b/analyze_hosts.py index 4348950..0f85d4b 100755 --- a/analyze_hosts.py +++ b/analyze_hosts.py @@ -988,7 +988,7 @@ def process_host( """ while host_queue.qsize() and not stop_event.wait(0.01): try: - host = host_queue.get() + host = host_queue.get(block=False) host_logfile = ( host + "-" + next(tempfile._get_candidate_names()) ) # pylint: disable=protected-access