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()は、longjmp()から呼び出された場合、デフォルトで0を返します.2番目のarg値は何でも、その値が返されます。SIGALRMが2度目に動作しないのはなぜですか?

+2

コードをインデントしてください。インデントされていないときは、読みにくいです! –

+1

'setjmp()'は最初に呼び出されたときにゼロを返し、 'longjmp()'からの戻り値がゼロでないときにはゼロを返します。あなたの 'printf()'も改行で終わらせるべきです。それ以外の場合は、出力が表示されないことがあります。 –

+0

@JonathanLefflerは 'printf()'の変更を行ってもまだ動作しません! – neileap

答えて

4

longjmp関数は、シグナルハンドラを呼び出すための安全関数とはみなされません。

実際にシグナルハンドラを残すことはないので、プロセスのコンテキストはシグナルハンドラのコンテキストになります。では、最初のシグナルハンドラを残していないときに、別のシグナルハンドラをどのように呼び出すことができますか?だから、あなたがしていることをしてはいけないのです。

代わりに、シグナルハンドラにフラグを設定して、代わりにそのフラグをループでポーリングしてください。シグナルハンドラから正常に戻り、プロセスを通常のように進める。

2

このコードはGCC 6.1.0でMac OS X 10.11.6で動作するようになっていますが、他の場所で動作しないようにするために複数のことがあります。とりわけ、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()ステートメントの後に改行を追加するだけで問題がないのかどうか分かりません。

関連する問題