2016-12-25 6 views
4

APUE本によると:sig_int_flagのテストの後、しかしpauseへのコールの前にシグナルが発生すると、プロセスは永久にスリープ状態になる可能性があります。シグナルが一時停止すると、プログラムは永久にスリープ状態になるのはなぜですか?

なぜ、誰かが私に教えてくれるのですか? ありがとうございました。

int sig_int();     /* my signal handling function */ 
int sig_int_flag;    /* set nonzero when signal occurs */ 

int main() { 
    signal(SIGINT, sig_int) /* establish handler */ 
    . 
    . 
    . 
    while (sig_int_flag == 0) 
     pause();    /* go to sleep, waiting for signal */ 
} 

int sig_int() { 
    signal(SIGINT, sig_int); /* reestablish handler for next time */ 
    sig_int_flag = 1;   /* set flag for main loop to examine */ 
} 
+1

'SIGNT'が処理される前に' while'条件がテストされた場合、 'sig_int_flag'は初期化されずに読み込まれるため、コードはUBに実行されます。 – alk

+0

次の 'SIGINT'が処理されるまで、" *。〜永遠にスリープ状態になります* "。 – alk

+0

@alkはグローバルなのでゼロではないでしょうか?私はこれが正しいと言っているわけではありません。 –

答えて

1

割り込み信号はあなたが記述している正確な時に発行されている場合:

  • をフラグがfalseにチェックされています入力ループ
  • 信号は、1にフラグを設定し、自分自身をリセットループが既に入力されているので、遅い(テストが完了した)
  • pause()が呼び出され、プログラムは待機します。

CTRL + C/SIGINTがもう一度トリガされた場合、ループを終了することができます。その信号は手動で発行できるので、それほど重要ではありません。

あなたがその動作を確認したい場合は、私はあなたがsleepステートメントを追加提案:

while (sig_int_flag == 0) 
{ 
    printf("Hit CTRL+C in the next 10 seconds to trigger the bug\n"); 
    sleep(10); 
    pause();    /* go to sleep, waiting for signal */ 
} 

回避策はpause()ステートメントを削除し、ポーリングループによってそれを置き換えるために、次のようになります。

while (sig_int_flag == 0) 
{ 
    sleep(1); 
} 

whilesleepの間を含むループのどこかでSIGINTが発生すると、プログラムがフラグがセットされていることに気付く前に1秒間待つことが悪化しますループが終了し、ループが終了すると、sleepコールが中断され、ループが直ちに終了するので、SIGINTが唯一の場合は、pauseコールとの間に目に見える違いはほとんどありません。

関連する問題