2017-03-17 3 views
1

のデフォルトアクションを変更することはできません、私はSIGINT信号をキャッチし、 のようなメッセージをプリントアウトしたいのsigactionを使用してはCでSIGINT

sa.sa_sigaction = handler; 

Iドンを経由してそれに新しいハンドラを渡すことで「SIGINTを受け取りました」プログラムを終了したくない。

シェルでプログラムを実行し、Ctrl + cで信号を生成すると、シグナルハンドラが信号を捕捉してメッセージを出力します。

その後、プロセスを終了させるデフォルトのアクションが実行されます。

私は間違っていますか?

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <fcntl.h> 
#include <string.h> 
#include <signal.h> 

static void handler(int sig, siginfo_t* si, void *unused){ 
    if(sig == SIGINT){ 
     printf("Signal %i received\n",si->si_signo); 
    } 
} 

int main(int argc, char* argv[]){ 
    char s [256]; 


    struct sigaction sa; 

    sigemptyset(&sa.sa_mask); 
    sigaddset(&sa.sa_mask, SIGINT); 
    sa.sa_flags = SA_SIGINFO; 
    sa.sa_sigaction = handler; 

    if(sigaction(SIGINT, &sa, NULL) < 0){ 
     perror("sigaction"); 
    } 

    fgets(s,sizeof(s), stdin); 
    printf("%s", s); 
    return 0; 
} 
+0

あなたはsigactionの後でメインから戻る前に何をしますか? – rici

+0

コードを更新しました。私は単にユーザー入力をエコーし​​ます。 –

+0

だから、sigintがあなたのプログラムを終了させる方法を知っていますか?私はfgetsが戻るので、ちょうど終了すると思います。 – rici

答えて

1

問題はfgetsreadシステムコールを呼び出します、とSIGINTによって中断時にシステムコールがエラーを返します、読み取りのmanページを参照してくださいということです。

EINTR呼び出しがによって中断されましたデータが読み取られる前の信号。 signal(7)を参照してください。

だから、fgetserrnoをチェックし、それがあった場合EINTRfgetsを呼び出すために継続すべきです。アップデートされたプログラムを試してみてください:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <fcntl.h> 
#include <string.h> 
#include <signal.h> 
#include <errno.h> 

static void handler(int sig, siginfo_t* si, void *unused){ 
    if(sig == SIGINT){ 
     printf("Signal %i received\n",si->si_signo); 
    } 
} 

int main(int argc, char* argv[]){ 
    char s [256]; 


    struct sigaction sa = {0}; 

    sigemptyset(&sa.sa_mask); 
    sigaddset(&sa.sa_mask, SIGINT); 
    sa.sa_flags = SA_SIGINFO; 
    sa.sa_sigaction = handler; 

    if(sigaction(SIGINT, &sa, NULL) < 0){ 
     perror("sigaction"); 
    } 

    char *p; 
    do { 
     p = fgets(s,sizeof(s), stdin); 
    } while (!p && errno == EINTR); 
    printf("%s\n", s); 
    return 0; 
} 
+0

あなたは正しいです...私は読み込みシステムコールを忘れていました。私は無限ループ(wihle(1))で試してみました。 –

+0

あなたは大歓迎です! :P – fluter

関連する問題