Установка обработчика сигналов с помощью Python

(есть ответ на этот вопрос здесь)

Я работаю над попыткой написать систему инициализации на основе Python для Linux, но у меня возникла проблема с получением сигналов для моего сценария инициализации Python. Со страницы «Убить человека 2»:

The only signals that can be sent to process ID 1, the init process,  are  those for which init has explicitly installed signal handlers.

В моем Init на основе Python у меня есть тестовая функция и настройка обработчика сигналов для вызова этой функции:

def SigTest(SIG, FRM):
    print "Caught SIGHUP!"

signal.signal(signal.SIGHUP, SigTest)

С другого TTY (скрипт инициализации выполняет sh на другом tty), если я посылаю сигнал, он полностью игнорируется, и текст никогда не печатается. kill -HUP 1

Я обнаружил эту проблему, потому что я написал функцию сбора урожая для моего Python init, чтобы пожинать его дочерние процессы, когда они умирают, но все они просто зомбированы, потребовалось некоторое время, чтобы понять, что Python никогда не получает сигнал SIGCHLD. Просто чтобы убедиться, что моя среда в порядке, я написал программу на C для разветвления, и ребенок отправил сигнал PID 1, и он зарегистрировался.

Как мне установить обработчик сигналов, который система будет подтверждать, если signal.signal(SIG, FUNC) не работает?

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

Идеи?

(Я не программист, я действительно не в себе :p)

Тестовый код ниже...

import os
import sys
import time
import signal


def SigTest(SIG, FRM):
    print "SIGINT Caught"

print "forking for ash"
cpid = os.fork()
if cpid == 0:
    os.closerange(0, 4)
    sys.stdin = open('/dev/tty2', 'r')
    sys.stdout = open('/dev/tty2', 'w')
    sys.stderr = open('/dev/tty2', 'w')
    os.execv('/bin/ash', ('ash',))

print "ash started on tty2"

signal.signal(signal.SIGHUP, SigTest)

while True:
    time.sleep(5.0)

person tMC    schedule 29.04.2011    source источник


Ответы (1)


Обработчики сигналов в основном работают на Python. Но есть некоторые проблемы. Во-первых, ваш обработчик не будет работать до тех пор, пока интерпретатор повторно не войдет в интерпретатор байт-кода. если ваша программа заблокирована в функции C, обработчик сигнала не вызывается до тех пор, пока он не вернется. Вы не показываете код, где вы ждете. Вы используете signal.pause()?

Другой заключается в том, что если вы находитесь в системном вызове, вы получите исключение после возврата обработчика singal. Вам нужно обернуть все системные вызовы обработчиком повтора (по крайней мере, в Linux).

Интересно, что вы пишете замену init... Это что-то вроде диспетчера процессов. Вас может заинтересовать код proctools, так как он обрабатывает SIGCHLD.

Кстати, этот код:

import signal

def SigTest(SIG, FRM):
    print "SIGINT Caught"

signal.signal(signal.SIGHUP, SigTest)

while True:
    signal.pause()

Работает ли в моей системе.

person Keith    schedule 29.04.2011
comment
Я не использую signal.pause(), я попробую. Я отредактировал сообщение с тестовым кодом, который я использовал - person tMC; 29.04.2011
comment
Ага, функция sleep() блокирует ваши обработчики сигналов до тех пор, пока она не завершится. Вот почему мне пришлось написать альтернативный сон< /а> модуль. Он вызывает C API PyErr_CheckSignals при прерывании. Это позволяет вызывать обработчики сигналов. - person Keith; 29.04.2011
comment
изменение sleep() на signal.pause() тоже не сработало. Я также попытался изменить sleep() на 0,01 (чтобы он казался более мгновенным), но сигнал так и не был пойман. Ядро? должны блокировать все сигналы ... должна быть разница между тем, как программа C и программа Python устанавливают обработчики сигналов. - person tMC; 29.04.2011
comment
Есть разница в том, как он обращается с ними. Как я уже сказал, я использую сигналы с Python, но со своими изменениями. - person Keith; 29.04.2011
comment
выполняя strace для скомпилированной программы C и сценария python, которые оба настраивают обработчики сигналов, похоже, что они оба используют системный вызов «rt_sigaction». однако похоже, что программа python пытается настроить ее 2 раза для одного и того же сигнала - первый раз как нуль, а затем с функцией? rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGINT, {0x4d7270, [], SA_RESTORER, 0x7f928fce0b40}, {SIG_DFL, [], 0}, 8) = 0. Может быть, он регистрирует только первый? - person tMC; 29.04.2011
comment
Кстати, ваш метод изменения stdio не будет работать, так как вы меняете только объекты python. Вы не влияете на базовые файловые дескрипторы. - person Keith; 29.04.2011
comment
@keith этот код работает? вы используете в качестве инициализации? Init, кажется, имеет специальную фильтрацию сигналов вокруг него. изменение stdio открывает консоль / bin / ash на tty2 - вот как я пытаюсь отправить сигналы на PID 1, мой сценарий инициализации - person tMC; 29.04.2011
comment
Нет, автономный. Сначала заставьте свою программу работать таким образом, а затем попробуйте ее как init. - person Keith; 29.04.2011
comment
он работал автономно, и только когда я сделал его init, он перестал получать сигналы SIGCHLD и не собирал своих мертвых детей, вот когда я обезжирил до крошечного тестового сценария. :( - person tMC; 29.04.2011
comment
Ой. Что ж, справочная страница init описывает, как init будет реагировать на SIGHUP, так что, похоже, там нет какой-либо специальной обработки. Вы уверены, что интерпретатор Python - это процесс 1? - person Keith; 29.04.2011
comment
да я уверен. из термина золы я могу cd /proc/1 и проверить файл состояния и т. д. Страница руководства по инициализации ссылается на то, что делает программа инициализации в стиле SysV (написанная на C). Могу ли я пропустить использование сигнального модуля и зарегистрировать обработчик с правильным fcnlt? или в libc с ctypes? Имеет ли это хоть какой-то смысл? - person tMC; 29.04.2011
comment
inits stdout по умолчанию /dev/console по умолчанию, я полагаю, он печатает из tty1, тот же экран, на котором печатаются загрузочные сообщения ядра - person tMC; 29.04.2011
comment
Тогда мне придется попробовать это самому. - person Keith; 29.04.2011
comment
@keith Я тестирую в KVM vm, я могу поделиться им с вами, если хотите, иначе просто дайте вам корзину python и связанные библиотеки (python построен против uClibc) - person tMC; 29.04.2011