Python и обработчики сигналов - PullRequest
0 голосов
/ 12 сентября 2018

Мне нужны некоторые пояснения относительно обработчиков сигналов в python, так как я не совсем понимаю, как они работают, как я могу их использовать и каковы ограничения.

Я намереваюсь использовать сигналы USR в linux для связи с программой на python, работающей в фоновом режиме, в качестве службы.

Я обнаружил, что, как и предполагалось, сигналы, которые я посылаю, похоже, обрабатываются немедленно асинхронно.

Поэтому я привык думать, что зарегистрированные обработчики сигналов работают в своих собственных потоках, что, как я думал, объясняет, почему следующий код будет печатать несколько строк Signal handler called with signal 10 одновременно при отправке сигналов в цикле

#!/usr/bin/python3.5
# This is the file signal_example.py

import signal, time, os

def handler(signum, frame):
    print('Signal handler called with signal', signum)
    time.sleep(20)

signal.signal(signal.SIGUSR1, handler)

time.sleep(100)


#!/usr/bin/bash
for ((i=0;i<100;i=i+1)); do 
    killall -s SIGUSR1 signal_example.py; 
done

Однако в документации говорится (https://docs.python.org/3.4/library/signal.html) "Обработчики сигналов Python всегда выполняются в основном потоке Python, даже если сигнал был получен в другом потоке.". Также я не вижу отдельных потоков, работающих на моем Система для приведенного выше примера.

Теперь мне интересно, каковы действительные последствия и ограничения моего подхода к использованию сигналов и как я могу правильно делать соответствующие вещи, такие как связь между экземплярами вызываемых обработчиков сигналов.

Например, в некоторых случаях я хотел бы иметь возможность отложить выполнение некоторого кода внутри обработчика сигналов до тех пор, пока не будут обработаны предыдущие сигналы того же типа. Также я не понимаю, сколько сигналов будет обрабатываться «параллельно» и что происходит, когда «очередь» заполнена ...

Я немного изучил Pyhton asyncio, который, кажется, предлагает некоторый контроль асинхронного кода, а также предлагает свой собственный способ регистрации обработчиков сигналов. Похоже, что он предлагает некоторые вспомогательные средства, но, похоже, он мне не очень помогает, поскольку поведение, которое я вижу (сигналы обрабатываются в значительной степени при их получении), на самом деле то, что я хочу. Использование обработчиков сигналов asyncio, которые я видел, похоже, выполняет сигналы в цикле событий. В частично блокирующем коде, с которого я начинаю, может быть слишком поздно. Я мог бы запустить некоторые из них в отдельных потоках (используя соответствующие функции asyncio), но не сделать весь код неблокирующим.

1 Ответ

0 голосов
/ 12 сентября 2018

Я намерен использовать сигналы USR в linux для связи с программой на python, работающей в фоновом режиме в качестве службы.

Это звучит как очень плохая идея.Вот несколько причин, почему:

  • Сигналы Unix доставляются асинхронно, что означает, что вы можете получить сигнал, когда выполняется любой код библиотеки, например, в середине вызова malloc.По этой причине только небольшое количество функций async-signal-safe , то есть безопасно вызывать из обработчика сигнала.Код Python вообще не может выполняться внутри обработчика сигнала, поэтому обработчик, установленный signal.signal, не выполняет функцию Python, а просто устанавливает глобальный флаг.Этот флаг время от времени проверяется основным потоком, который выполняет функцию обработчика Python.Это означает, что нет гарантии, что сигнал будет доставлен немедленно, т. Е. Вы не можете полагаться на гарантии доставки сигнала, предоставляемые операционной системой.

  • Сигнал может поступить во время выполненияобработчик предыдущего сигнала.Вот почему вы видите, как печатаются несколько строк, это артефакт самого обработчика сигнала, который прерывается сигналом и снова входит в него.

  • Если вы не настроили обработчики сигналов с помощью специализированных вызовов POSIX(и обработчики, настроенные с помощью этих вызовов, не могут напрямую выполнять код Python), сигналы не будут поставлены в очередь.Даже когда они находятся в очереди, за исключением сигналов не в реальном времени, порядок сигналов между генерацией и доставкой не сохраняется.

  • Сигналы действительно плохо взаимодействуют с многопоточным кодом, дажев чистом C.

Если у вас есть служба, с которой вам нужно взаимодействовать, вы можете иметь поток, который читает из именованного канала или прослушивает сокет.Запись в канал или открытие сокета послужит сигналом для процесса.Это также позволяет передавать дополнительную информацию службе.

...