2013-11-14 1 views
3

У меня есть код python, который работает непрерывно (сбор данных датчика). Он должен быть запущен при загрузке с использованием start-stop-daemon. Тем не менее, я хотел бы умело убить процесс, поэтому я начал с совета в сообщении How to process SIGTERM signal gracefully? и поместил мой основной цикл в отдельный поток. Я бы хотел, чтобы он был изящно закрыт его, когда он работает как демон (start-stop-daemon отправит сигнал об уничтожении), и когда я запускаю его ненадолго для тестирования в терминале самостоятельно (я нажимаю ctrl-c).Почему сигнал.SIGTERM не обрабатывается должным образом в моей основной теме?

Однако обработчик сигнала, похоже, не вызывается, если я убью процесс (даже без использования потока, «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)) 

ответ

4

Вы прекращаете свой основной поток с этим утверждением:

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)" 
+0

Но как основной поток затем конец? (Действительно, отправка 'kill ' остановила вывод данных в файл, но процесс python по-прежнему отображается с тем же , когда я делаю 'ps'). Кроме того, я думал, что где-то я читал, что при использовании 'Thread (..). Start()' вызывающий поток ожидает завершения порожденного потока (в отличие от 'thread.start_new_thread' из библиотеки' thread') – Rabarberski

+0

Нить может быть помечен как «поток демона». Значение этого флага заключается в том, что вся программа Python завершается, когда остаются только потоки демона. Начальное значение наследуется от создающего потока. Флаг может быть установлен с помощью метода setDaemon() и получен с помощью метода isDaemon(). – jramirez

+0

Вы не сделали это демоном. – jramirez

Смежные вопросы