2010-03-10 2 views
10
#include<stdio.h> 
#include<signal.h> 

void handler(int signo) 
{ 
    printf("Into handler\n"); 
    while(1); 
} 
int main() 
{ 
    struct sigaction act; 
    act.sa_handler = handler; 
    act.sa_flags = 0; 
    sigemptyset(& act.sa_mask); 
    sigaction(SIGINT, &act, NULL); 
    while(1); 
    return 0; 
} 

После ловли KeyboardInterrupt один раз, когда я нажимаю «Ctrl + C» снова, SIGINT не обрабатывается ... я намереваюсь, что «В обработчике» должен быть напечатан каждый раз, когда я , нажмите «Ctrl + C».Поймав сигнал внутри своего собственного обработчика

Я хочу, чтобы поймать SIGINT внутри «SIGINT обработчик()» сам ..

ответ

10

Вы должны установить SA_NODEFER на sa_mask поймать тот же сигнал, как и тот, который вы в настоящее время обработки:

SA_NODEFER: Не мешайте сигнал от принимается внутри своего собственного обработчика сигнала. SA_NOMASK - устаревший, нестандартный синоним этого флага.

+0

Я получил то, что хотел .. Thanx .. :) –

+0

Остерегайтесь: это не гарантирует, что вы не потеряете сигналы! Если ваш процесс получает несколько сигналов, отличных от реального времени одного и того же типа, когда он не находится во временном интервале или в режиме бесперебойного вызова ядра, то второй (и далее) сигналы будут потеряны. – peterh

1

«в то время как (1)» в обработчике мешает первый вызов службы когда-либо возвращаться. Удалите это и последующие прерывания, чтобы снова вызвать обработчик.

Процедура обслуживания прерываний не должна препятствовать возврату вызывающего потока.

+0

Я хочу поймать SIGINT внутри самого обработчика SIGINT(). –

+1

Затем перепишите свое ядро ​​Unix. – kmarsh

6

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

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

Вызов printf из обработчика сигналов - это неопределенное поведение. Это может привести к сбою вашей программы. Список функций, которые вы фактически можете безопасно вызывать из обработчика сигнала, очень ограничен. I need a list of Async-Signal-Safe Functions from glibc

+0

+1 «по-видимому, очень плохая идея». В общем, держать ваши обработчики сигналов как можно короче и проще - это путь. –

+0

вот почему я написал «sigemptyset (& act.sa_mask);» так что сигнал не замаскирован. Где я ошибаюсь? –

+0

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

3

Использование функции printf внутри обработчика сигнала не точно хорошая идея, чтобы использовать, поскольку это может вызвать поведение, которое не определено! В образце кода отсутствует жизненно важный бит для обработки обработчика сигнала. Посмотрите на мой блог об этом here на 'Q6. Как уловить недостаток сегментации? '

Кроме того, вам необходимо заменить петлю на что-то более надежное, чтобы выйти из программы во время тестирования обработчика сигнала ... например ... как вы его покинете?

+0

Я только что начал читать о сигналах ... Итак, что это за правильный путь? –

+0

Посмотрите на код, вы будете «sigemptyset», затем установите флаги и «sigaction (SIGINT, & sigact, (struct sigaction *) NULL); вызывается после него ... который ловушки SIGINT .. вы устанавливаете флаги перед вызовом 'sigemptyset' .. btw это использовалось в рабочей среде и работает с радостью в AIX ... – t0mm13b

2

Вы можете использовать что-то вроде этого вместо Printf:

const char *str = "Into handler\n"; 
write(1, str, strlen(str)); 

Функция write(..) безопасна для вызова из сигнала hanlder. Не забудьте включить заголовок unistd.h, чтобы использовать его.

+1

Вероятно, вы более безопасны, ссылаясь на 'stdout 'а не' 1', поскольку различные средства могут привести к изменению этого числа. – RastaJedi

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