2014-02-18 4 views
1

Так у меня есть этот код (частично взято из питона Документов):Python signal.signal предотвращает распространение?

import signal 

def handler(signum, frame): 
    print 'Signal handler called with signal', signum 

s = signal.signal(signal.SIGINT, handler) 

some_fancy_code() # this code is using subprocess.Popen() to call another script 

singal.signal(signal.SIGINT, s) 

То, что я нашел прямо сейчас, что если я Ctrl + C в моей программе, он правильно поступает, что обработчик и печатает. Теперь, я думал, что после получения Ctrl + C мой обработчик будет подавлять обработчик по умолчанию, поэтому, например, мой подпроцесс. Popen не получит сигнал KeyboardInterrupt. Но это не так.

Но когда мы заменяем «обработчик» на «signal.SIG_IGN», это распространение никогда не происходит. Модифицированный фрагмент кода:

import signal 

s = signal.signal(signal.SIGINT, signal.SIG_IGN) 

some_fancy_code() # this code is using subprocess.Popen() to call another script 

singal.signal(signal.SIGINT, s) 

Является ли это потому, что SIG_IGN является своим родом сигнала «волшебного», написанным в самом языке? Или, может быть, есть способ сделать подобное подавление в моем собственном обработчике?

После прочтения вопроса о переполнении стека я немного смущен. Если бы кто-то мог объяснить мне, почему такая разница в поведении.

ответ

2

Это заданное поведение POSIX сигналов:

A child created via fork(2) inherits a copy of its parent's signal dis‐ 
    positions. During an execve(2), the dispositions of handled signals 
    are reset to the default; the dispositions of ignored signals are left 
    unchanged. 

При выполнении (вилка/execve) ваш другой сценарий в первом случае, обработчик SIGINT сбрасывается обработчик по умолчанию в другом сценарии (поведение по умолчанию - это прекращение процесса) - конечно, другой скрипт может установить собственный обработчик и изменить это поведение.

Однако во втором случае вы настроили SIGINT для игнорирования. Это поведение будет распространено на другой скрипт, как указано в определении выше. Опять же, другой скрипт мог изменить это поведение, установив собственный обработчик.

Так что это не имеет никакого отношения к Python напрямую. Это ожидаемое поведение реализации обработки сигналов POSIX базовой операционной системы.

PS. Если вам интересно, что такое fork() и execve(), fork() создает копию текущего процесса (дочернего) и execve() заменяет текущий процесс другим. Это основной механизм, используемый subprocess.Popen() для запуска «другого сценария»: сначала создайте копию текущего процесса и затем замените его на целевой процесс.

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