2016-08-09 9 views
1
#include<stdio.h> 
#include<setjmp.h> 
#include<signal.h> 

jmp_buf env; 

void alarmHandler() 
    { 
     printf("\n in alarm Handle"); 

     longjmp(env,1); 
    } 



int main() 
    { 
     signal(SIGALRM,alarmHandler); 

     alarm(2); 

    for(;;) 
    { 
     printf("\nhello"); 
     sleep(1); 

     if(setjmp(env)) 
      { 

       printf("\n inside if"); 
       signal(SIGALRM,alarmHandler); 
       alarm(2); 
      } 

    } 


return 0; 

    } 

При запуске активаторы контролируют сигнал, затем активную тревогу в течение 2 секунд (обратный отсчет). Внутри цикла for, каждый раз, он сохраняет экономию setjmp(env) со временем заканчивается последним setjmp(env) будет называться с использованием longjmp(). Как setjmp() по умолчанию возвращает 0, если вызвано из longjmp(), что бы то ни было второе значение аргумента - это возврат значения.Почему SIGALRM не работает второй раз?

+2

Отклоните свой код; это действительно трудно читать, когда нет отступов! –

+1

Обратите внимание, что 'setjmp()' возвращает ноль при первом вызове и возвращает ненулевое значение, когда return из 'longjmp()'. Вы также должны закончить свой 'printf()' символом новой строки. В противном случае вывод может не отображаться. –

+0

@JonathanLeffler сделал изменение в 'printf()' все еще не работает! – neileap

ответ

4

Функция longjmp не считается безопасной функцией вызова обработчиков сигналов.

Подпрыгивая так, что вы никогда не покидаете обработчик сигнала, контекст процесса по-прежнему будет контекстом обработчика сигнала. Итак, как можно вызвать вызов другого обработчика сигнала, когда мы даже не оставили первый? Вот почему вы не должны делать то, что делаете.

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

2

Я получил этот код для работы с Mac OS X 10.11.6 с GCC 6.1.0, но есть несколько вещей, которые могут помешать работе в другом месте. Среди прочих, POSIX не обозначает longjmp() или siglongjmp() как безопасный для использования в обработчике сигнала (см. POSIX Signal Concepts). Вы не должны использовать printf() - или strlen() либо - в обработчике сигналов.

Мои параметры компиляции по умолчанию требуют, чтобы обработчик тревоги был статическим или объявлен до его определения; аргумент необходим, чтобы избежать несоответствий в типе указателя, переданного в signal(); необходимо использовать номер сигнала (но для этого я мог бы использовать longjmp(env, signum)).

Однако вы часто можете избежать злоупотребления правилами.

#include <stdio.h> 
#include <setjmp.h> 
#include <signal.h> 
#include <unistd.h> 

jmp_buf env; 

static 
void alarmHandler(int signum) 
{ 
    printf("\nin alarm Handle (%d)\n", signum); 
    longjmp(env, 1); 
} 

int main(void) 
{ 
    signal(SIGALRM, alarmHandler); 

    alarm(2); 

    for (; ;) 
    { 
     printf("\nhello"); 
     sleep(1); 

     if (setjmp(env)) 
     { 
      printf("\ninside if\n"); 
      signal(SIGALRM, alarmHandler); 
      alarm(2); 
     } 
    } 
    printf("Exiting\n"); 

    return 0; 
} 

Пример вывод:

hello 
hello 
in alarm Handle (14) 

inside if 

hello 
hello 
in alarm Handle (14) 

inside if 

hello 
hello 
in alarm Handle (14) 

inside if 

hello 
hello 
in alarm Handle (14) 

я заскучал и прервал его в этой точке.

Я не уверен, что добавление новых строк после сообщений printf() достаточно, чтобы заставить его работать.

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