After Lifecycle is terminated (via SIGINT or a call to terminate), threads are left dangling, stuck in while True loops which will never complete.
Audit such loops (cursory examination suggests new_block_watch and _start_event_timer are the main culprits) and ensure they cleanly exit. Consider thread.joining them to make disposal more deterministic.