簡體   English   中英

Ctrl-C被getchar()吃掉

[英]Ctrl-C eaten by getchar()

我一直在尋找解決我問題的方法很長一段時間,這就是我轉向你的原因:

考慮一下這段代碼:

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 + C字符被getchar()調用吃掉,並且從不執​​行sigHandler函數。 按下CTRL + C然后按Enter鍵時,將調用sigHandler函數並退出程序。

有經驗和知識的人可以幫助我嗎?

感謝您的輸入 :)

代碼實際上正在按預期工作 - 直到從user_input()返回之后才測試done標志,這就是為什么你需要在control-C之后輸入一個額外的字符。

如果你想在獲得control-C時中止對getchar的調用,那么你可能不得不做一些丑陋的事情,例如使用setjmp / longjmp

Ctrl-C字符被getchar()調用吃掉,並且從不執​​行sigHandler函數。

getchar不會吃掉Ctrl-C; 它導致傳遞信號並運行sigHandler 這設置done並返回。 只有這樣才會調用getchar ,它會占用換行符, 然后檢查done ,以便程序退出。

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

有一種方法可以在不訴諸丑陋的黑客的情況下中止呼叫(與Paul R所說的相反)。 你應該使用sa_flags設置為0而不是signal() sigaction() 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調用sigaction來更改此行為。

這樣,在處理SIGINT之后, getchar將返回-1並且errno將被設置為“Interrupted system call”(我現在不記得常量名稱)。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM