2013-12-21 4 views
2

Я использую версию python 2.7 на ubuntu. Мне интересно, как различные сигналы обрабатываются в программе python во время ее выполнения. Есть ли выбор на основе приоритета? Например: если в то же время генерируются два разных сигнала, какой из них будет подан первым? В моей приведенной ниже программе он ждет, когда пользователь нажмет клавишу Ctrl-C, если это будет сделано, это покажет, что «Процесс нельзя убить с помощью клавиши ctrl-c!». Наряду с этим он продолжает генерировать сигнал SIGALRM каждую секунду и каждый раз генерирует сообщение «Got alarm».Как различные сигналы обрабатываются в python

#!/usr/bin/env python 
import signal 
import time 

def ctrlc_catcher(signum, frm): 
    print "Process can't be killed with ctrl-c!" 

def alarm_catcher(signum,frame): 
    print "Got an alarm" 


signal.signal(signal.SIGINT, ctrlc_catcher) 
signal.signal(signal.SIGALRM, alarm_catcher) 


while True: 
    signal.alarm(1) 
    time.sleep(1) 
    pass 

Теперь, когда я выполняю программу она производит следующий вывод на неопределенный срок:

Got an alarm 
Got an alarm 
Got an alarm 
Got an alarm 

Если во время выполнения я ударил клавишу Ctrl-C один раз, то выходной сигнал прерывается, и, как показано ниже:

Got an alarm 
Got an alarm 
Got an alarm 
Got an alarm 
Process can't be killed with ctrl-c 
Got an alarm 

Все работает как запрограммировано и как ожидалось. Мой вопрос, если нажать клавишу Ctrl-C непрерывно, то почему выход, как указано ниже:

Process can't be killed with ctrl-c 
Process can't be killed with ctrl-c 
Process can't be killed with ctrl-c 

Почему не выход относительно срабатывание сигнализации также отображается в выводе выше в качестве будильника запускается каждую секунду? Игнорируется ли сигнал тревоги (signal.ALARM) из-за сигнала. SIGNIT? Или непрерывное нажатие клавиши Ctrl-C приостанавливает что-то? Thanks

ответ

3

поведение вы видите из-за взаимодействия двух факторов:

(1) При вызове signal.alarm, вы очищаете все предыдущие сигналы тревоги; после вызова запланирован только самый последний запрошенный сигнал.

(2) Сигнал пойманного сигнала заканчивается time.sleep и вызывает сокращение сна; он не возобновляется после возврата обработчика сигнала.

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

Из этого следует, что если вы нажимаете cntl-C чаще, чем один раз в секунду, вы вообще не увидите "Got an alarm.".

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

+0

Спасибо и +1 за разъяснение! –

0

Возможно, что-то вроде этого?

#!/usr/local/cpython-3.3/bin/python 

import subprocess 

p = subprocess.Popen("./app", 
     stdin = subprocess.PIPE, 
     stdout = subprocess.PIPE, 
     stderr = subprocess.PIPE, 
     shell = True) 
p.stdin.write(bytes("3\n", "ascii")) 
p.stdin.write(bytes("4\n", "ascii")) 
print(p.stdout.read()) 
exit_code = p.wait() 
print(exit_code) 
+0

Что это связано с прерываниями и сигналами тревоги? –

+1

Неверный вопрос, возможно? Вы хотите опубликовать это на [p.stdout.read() не работает в моих кодах Python 3] (http://stackoverflow.com/q/20724549)? –

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