#python #multithreading #conditional-statements #wait
#python #многопоточность #условные операторы #подождите
Вопрос:
У меня есть следующий код, который при выполнении ожидает прерывания на SIGINT
, SIGTERM
или SIGQUIT
. Когда объект инициализируется, он создает threading.Condition()
и acquires()
это! Затем программа регистрирует обработчики сигналов, где notify()
и release()
вызывается при получении вышеупомянутых сигналов. После регистрации обработчиков сигналов он вызывает wait()
переменную условия и блокирует.
Когда я попытался остановить программу с помощью Ctrl-C
, она не ответила. Итак, _signal_handler()
метод не был вызван.
# start
from signal import signal, SIGINT, SIGTERM, SIGQUIT
from threading import Condition
class A:
def __init__(self):
self._termination_signal = Condition()
self._termination_signal.acquire(blocking=0)
def _signal_handler(self, signum, frame):
print "Received terminate request - signal = {0}".format(signum)
del frame
self._termination_signal.notify()
self._termination_signal.release()
return
def register_and_wait(self):
signal(SIGINT, self._signal_handler)
signal(SIGTERM, self._signal_handler)
signal(SIGQUIT, self._signal_handler)
print "Waiting to be interrupted!"
self._termination_signal.wait() # control blocks here!
print "Notified!!"
def main():
a = A()
a.register_and_wait()
if __name__ == "__main__":
main()
# end
Что я делаю не так?!
Ответ №1:
Похоже, что он зависает в обработчике сигнала, пытаясь получить блокировку переменной условия. Я не знаю почему, но другой вариант — просто дождаться сигнала.
from signal import pause, signal, SIGINT, SIGTERM, SIGQUIT
class A:
def __init__(self):
self._signum = 0
def _signal_handler(self, signum, frame):
print "Received terminate request - signal = {0}".format(signum)
self._signum = signum
return
def wait_for_signal(self):
signal(SIGINT, self._signal_handler)
signal(SIGTERM, self._signal_handler)
signal(SIGQUIT, self._signal_handler)
print "Pause until signaled"
while self._signum == 0:
pause()
def main():
a = A()
a.wait_for_signal()
main()
Причина проверки self._signum
заключается в том, что в случае пробуждения другого сигнала pause()
. Простым примером этого было бы SIGALRM
.
Комментарии:
1.
signal.pause()
только для Unix, лучше использовать какой-нибудь метод короткого ожидания, такой какtime.sleep(1.0)
илиthreading.Condition.wait(1.0)
для переносимости.2. @Tey’ Цель этого вопроса — избежать использования
threading.Condition.wait
, поскольку это вызывает этот сценарий взаимоблокировки, даже при вызове с таймаутом.