Почему signal.SIGTERM неправильно обрабатывается в моей основной ветке?
У меня есть код Python, который работает непрерывно (сбор данных датчика). Предполагается, что он запускается при загрузке с помощью start-stop-daemon
, Тем не менее, я хотел бы иметь возможность грациозно завершить процесс, поэтому я начал с рекомендации в посте Как правильно обрабатывать сигнал SIGTERM? и поместил мой основной цикл в отдельную ветку. Я хотел бы иметь возможность изящно выключить его, когда он работает как демон (start-stop-daemon
отправит сигнал уничтожения) и когда я его кратко запусту для тестирования в терминале (я нажимаю ctrl-c
).
Однако обработчик сигнала, кажется, не вызывается, если я убиваю процесс (даже без использования потока, " done (killed)
"никогда не попадает в файл, на который я перенаправлен). И когда я нажимаю ctrl-c
сбор только продолжается и продолжает печатать данные в терминале (или в файл, на который я перенаправляю).
Что я делаю не так в следующем коде?
from threading import Thread
import time, sys, signal
shutdown_flag = False #used for gracefull shutdown
def main_loop():
while not shutdown_flag:
collect_data() # contains some print "data" statements
time.sleep(5)
print "done (killed)"
def sighandler(signum, frame):
print 'signal handler called with signal: %s ' % signum
global shutdown_flag
shutdown_flag = True
def main(argv=None):
signal.signal(signal.SIGTERM, sighandler) # so we can handle kill gracefully
signal.signal(signal.SIGINT, sighandler) # so we can handle ctrl-c
try:
Thread(target=main_loop, args=()).start()
except Exception, reason:
print reason
if __name__ == '__main__':
sys.exit(main(sys.argv))
1 ответ
Вы заканчиваете свою основную тему этим утверждением:
if __name__ == '__main__':
sys.exit(main(sys.argv))
Таким образом, ваш обработчик сигнала никогда не запускается. Обработчик сигнала является частью основного потока, а не main_loop
нить вы создали. Таким образом, после выхода из основного потока больше не требуется вызывать функцию-обработчик сигнала.
Вам нужно что-то вроде этого:
def sighandler(signum, frame):
print 'signal handler called with signal: %s ' % signum
global shutdown_flag
shutdown_flag = True
sys.exit() # make sure you add this so the main thread exits as well.
if __name__ == '__main__':
main(sys.argv)
while 1: # this will force your main thread to live until you terminate it.
time.sleep(1)
Простой тест, чтобы увидеть, сколько потоков запущено в вашей программе:
def main_loop():
while not shutdown_flag:
collect_data() # contains some print "data" statements
time.sleep(5)
import threading
print threading.enumerate()
print "done (killed)"