Создавайте Daemon в конструкторе.
th = _ServerThread()
th.start()
th.stop()
Что можно легко поймать?
th.run еще не начал выполнятся, блокировки нет.
th.stop() захватывает блокировку и вызывает self._daemon.shutdown() для еще не существующего атрибута _daemon. Ахтунг
th.run на этот момент добрался до блокировки. Вы игнорируете try-finally при использовании блоков, исключение из th.stop блокировку не снимает.
th.run ждет доступа к блоку вечно, поток никогда не завершится.
Теперь предположим, что вашему Daemon все же нужно выполнить конструктор в том же потоке, в котором будет крутится его requestLoop. Еще допустим, что _daemon.shutdown() можно вызвать только один раз, второй все поломает (это не всегда верно).
import threading
class _ServerThread(threading.Thread):
_lock = None
_daemon = None
def __init__(self):
threading.Thread.__init__(self)
self._lock = threading.Lock()
self._condition = threading.Condition(self._lock)
self._started = False
self._stopping = False
def run(self):
try:
self._condition.acquire()
self._daemon=Daemon()
self._started = True
self._condition.notifyAll()
finally:
self._condition.release()
self._daemon.requestLoop() # Бесконечный цикл внутри
def stop(self):
try:
self._condition.acquire()
while not self._started:
self._condition.wait()
if not self._stopping:
self._daemon.shutdown()
self._stopping = True
finally:
self._condition.release()