Удовольствие от обработчиков сигналов в Python Interrupting Select - PullRequest
3 голосов
/ 15 октября 2011

Я работаю над проектом по программированию - пишу простое P2P-приложение для обмена файлами на Python. Я использую два потока: основной для вызова select и ожидания ввода из списка сокетов и sys.stdin (для получения напечатанных команд) и вспомогательный поток, который извлекает сообщения об обновлении статуса из очереди и печатает их. (Это единственное, что печатает что-либо)

Мне также необходимо поймать стандартный сигнал SIGINT и обработать его для корректного выхода. У меня есть метод выхода, который делает это; набрав 'quit' как команду, работает просто отлично. Поэтому в основном потоке я пытаюсь установить этот метод в качестве обработчика для SIGINT. Насколько я могу судить, процесс ловит сигнал и вызывает метод quit. Вспомогательный поток печатает сообщение, подтверждающее, что он завершается. Но тогда я получаю следующее сообщение об ошибке из основного потока:

Traceback (most recent call last):
  File "peer.py", line 226, in <module>
    main()
  File "peer.py", line 223, in main
    p.run()
  File "peer.py", line 160, in run
    readables, writables, exceptions = select(self.sockets, [], [])
select.error: (4, 'Interrupted system call')

После чего программа все еще завершает работу. Принимая во внимание, что без обработчика сигнала отправка SIGINT дает мне следующее:

Traceback (most recent call last):
  File "peer.py", line 225, in <module>
    main()
  File "peer.py", line 222, in main
    p.run()
  File "peer.py", line 159, in run
    readables, writables, exceptions = select(self.sockets, [], [])
KeyboardInterrupt

Что не может завершить программу; Я должен остановиться и убить это. Это сбивает с толку, потому что SIGINT, кажется, прерывает вызов select только тогда, когда он перехватывается моим пользовательским методом. (Который только помещает сообщение в очередь печати и устанавливает переменную «done») Кто-нибудь знает, как это может происходить? Это просто плохая идея пытаться использовать обработчики сигналов и потоки одновременно?

Ответы [ 2 ]

0 голосов
/ 19 октября 2011

Да, прошлой ночью после того, как я перестал работать над этим, я понял, что хочу, чтобы это прервалось.Это было прервано выполнением обработчика сигнала, предположительно.Поэтому я просто перехватываю select.error и заставляю его переходить в конец цикла, где он немедленно завершается и переходит к коду очистки.

0 голосов
/ 15 октября 2011

Я не уверен в использовании обработчиков сигналов для обнаружения этого случая, но я нашел рецепт для обработки этого случая в * nix системах: http://code.activestate.com/recipes/496735-workaround-for-missed-sigint-in-multithreaded-prog/

В двух словах (если я правильно предприму):

Перед тем, как запускать новые потоки, разветвите дочерний процесс (используя os.fork), чтобы завершить выполнение программы, и попросите родительский процесс наблюдать за KeyboardInterrupt.

Когда родитель перехватывает прерывание клавиатуры, вы можете уничтожить дочерний процесс (который к настоящему времени, возможно, запустил другие потоки), используя os.kill. Это, в свою очередь, прервет все потоки этого дочернего процесса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...