2017-03-17 48 views
1

更改默認操作在C語言中,我要趕在SIGINT信號,並打印出一個消息像 使用的sigaction並通過無法爲SIGINT

傳遞一個新的處理程序,以它
sa.sa_sigaction = handler; 

我不「收到SIGINT」不想終止程序。

如果我通過shell運行程序並用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之後和從main返回之前做了什麼? – rici

+0

我更新了代碼。我只是迴應用戶輸入。 –

+0

那麼你怎麼知道sigint終止你的程序?我認爲它只是完成,因爲fgets返回。 – rici

回答

1

的問題是,fgets將調用read系統調用,系統調用會返回一個錯誤時SIGINT打斷,看到讀手冊頁:

EINTR的調用被中斷在讀取任何數據之前的信號;見信號(7)。

所以,你應該檢查的fgetserrno,如果這是EINTR繼續看漲fgets。試試我的更新程序:

#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