Почему 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)"
Другие вопросы по тегам