2016-08-09 36 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; 

    } 

Beim Start überwachen die Aktiven das Signal und dann den aktiven Alarm für 2 Sekunden (Countdown). Innerhalb der for Schleife, jedes Mal, es speichert setjmp(env) als Zeit endet zuletzt setjmp(env) wird mit longjmp() aufgerufen werden. Als setjmp() standardmäßig 0 zurückgeben, wenn von longjmp() aufgerufen wird, was auch immer der zweite Arg-Wert ist, ist dieser Wert zurückgeben.Warum funktioniert SIGALRM nicht zum zweiten Mal?

+2

Bitte den Code einrücken; Es ist wirklich schwer zu lesen, wenn es keine Einrückung gibt! –

+1

Beachten Sie, dass 'setjmp()' beim ersten Aufruf Null zurückgibt und bei Rückgabe von 'longjmp()' ungleich Null zurückgibt. Sie sollten Ihre 'printf()' auch mit einem Zeilenumbruch beenden. Andernfalls wird die Ausgabe möglicherweise nicht angezeigt. –

+0

@ JonathanLeffler machte Änderung in 'printf()' immer noch nicht funktioniert! – neileap

Antwort

4

Die longjmp-Funktion wird nicht als sichere Funktion zum Aufrufen von Signalhandlern betrachtet.

Wenn Sie so springen, verlassen Sie nie den Signal-Handler, der Kontext des Prozesses ist immer noch der Kontext des Signal-Handlers. Wie könnte also ein anderer Signal-Handler aufgerufen werden, wenn wir nicht einmal den ersten verlassen haben? Deshalb solltest du nicht tun, was du tust.

Setzen Sie stattdessen ein Flag im Signalhandler und rufen Sie stattdessen dieses Flag in Ihrer Schleife ab. Kehren Sie dann normal vom Signalhandler zurück und lassen Sie den Prozess normal weiterlaufen.

2

Ich habe diesen Code unter Mac OS X 10.11.6 mit GCC 6.1.0 installiert, aber es gibt mehrere Dinge, die verhindern könnten, dass er woanders funktioniert. Unter anderem bezeichnet POSIX weder longjmp() noch siglongjmp() als sicher für die Verwendung in einem Signal-Handler (siehe POSIX Signal Concepts). Sie sollten printf() - oder strlen() entweder nicht verwenden - in einem Signal-Handler.

Meine Standard-Kompilierungsoptionen erfordern, dass der Alarmhandler statisch oder deklariert ist, bevor er definiert wurde. Das Argument ist notwendig, um Fehlanpassungen im Typ des an signal() übergebenen Zeigers zu vermeiden; die Signalnummer muss verwendet werden (aber ich könnte dafür longjmp(env, signum) verwenden).

Sie können jedoch oft mit dem Missbrauch der Regeln durchkommen.

#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; 
} 

Beispielausgabe:

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) 

Ich habe gelangweilt und unterbrach es an diesem Punkt.

Ich bin mir nicht sicher, ob das Hinzufügen der Zeilenumbrüche nach den printf() Anweisungen ausreicht, um es zu arbeiten.