2011-11-02 137 views
4

我一直在尋找一個解決我的問題很長一段時間,這就是爲什麼我要轉你:通過的getchar吃掉按Ctrl-C()

考慮這段代碼:

static char done = 0; 
static void sigHandler(void) 
{ 
    done = 1; 
} 

int user_input() 
{ 
    return (getchar() == 'q') ? 0 : 1; 
} 

int main(void) 
{ 
    signal(SIGTERM, sigHandler); 
    signal(SIGINT, sigHandler); 
    while (user_input() != 0 && !done) 
     usleep(1000); 
    printf("exiting\n"); 
    return 0; 
} 

預期行爲: 程序在用戶輸入q時退出,然後輸入。如果CTRL + C被按下,它被sigHandler函數捕獲,它將標誌'done'設置爲1並退出程序。

觀察到的行爲: 的CTRL + Ç字符被的getchar()調用吃掉,從不執行所述sigHandler功能。當CTRL + C然後按下,sigHandler函數被調用並且程序退出。

能有更多經驗和知識的人幫我解決那個問題嗎?

感謝您的輸入:)

+0

即使這是我一開始不想做的事情,我已經通過不使用標誌並從處理程序中退出來解決了我的問題。 –

回答

3

有一種方法可以在不訴諸醜陋的黑客的情況下中止呼叫(與Paul R所說的相反)。您應該使用sigaction()並將sa_flags設置爲0而不是signal()

另外,信號(2)手冊說:

避免其使用:使用的sigaction(2)來代替。

#include <stdio.h> 
#include <signal.h> 
#include <string.h> 
#include <errno.h> 

static char done = 0; 
static void sigHandler(int signum) 
{ 
    done = 1; 
} 

int user_input() 
{ 
    return (getchar() == 'q') ? 0 : 1; 
} 

int main(void) 
{ 
    struct sigaction sa; 
    memset(&sa, 0, sizeof(struct sigaction)); 
    sa.sa_handler = sigHandler; 
    sa.sa_flags = 0;// not SA_RESTART!; 

    sigaction(SIGINT, &sa, NULL); 
    sigaction(SIGTERM, &sa, NULL); 

    while (user_input() != 0 && !done) 
     usleep(1000); 
    printf("exiting\n"); 
    return 0; 
} 

通常情況下,捕捉和處理的信號後,大多數(我不知道,如果不是全部)系統調用將重新啓動。這樣,處理sigint信號後,您的getchar函數將繼續,就像沒有任何事情發生一樣。 您可以通過撥打sa_flags=0來改變此行爲。

這樣,在處理SIGINT後,getchar將返回-1並且errno將被設置爲「Interrupted system call」(我現在不記得常數名稱)。

你還必須重寫你的user_input()函數來處理返回-1時的情況。

+1

名稱是'EINTR'。 – ninjalj

+0

如果您在sa_flags中設置了SA_RESTART,那麼應該重新啓動系統調用。在實踐中,這通常不能正確實現,所以最好不要設置SA_RESTART,並期望系統調用可能因信號而終止。但是,getchar不是系統調用,它不會因信號過早返回。 –

+0

太好了!正是我在找什麼。謝謝!!! –

6

的代碼實際上是按預期工作 - 你是不是測試done標誌,直到你從user_input()返回後,這就是爲什麼你需要的控制 - 後進入附加字符C。

如果你想中止呼叫到getchar當你得到一個控制-C,那麼你可能不得不做一些醜陋的事情,例如,使用setjmp/longjmp

+0

謝謝。我認爲在獲得控制權時,會比放棄呼叫更聰明 - C –

5

Ctrl-C字符被getchar()調用吃掉,sigHandler函數永遠不會執行。

Ctrl-C不被getchar吃掉;它會導致信號正在傳輸並且運行sigHandler。這套done並返回。 只有getchar調用,它吃掉換行符和之後,done被選中,程序退出。

順便說一下,信號處理程序需要一個參數int,而不是void