Ctrl信号用EOF填充标准输入?

时间:2016-05-25 01:59:08

标签: c signals stdin

我正在使用解析器获取字符EOF,我处理信号SIGTERMSIGINTSIGTSTPSIGQUIT。所以当我用 Ctrl + C 例如 SIGINT)发送信号时,信号处理程序打印 Ctrl < / kbd> + C 然后必须继续,但不会继续。

我发现在每个 Ctrl 信号之后,EOF正在填充缓冲区,但我不知道如何摆脱它。我尝试在处理程序中执行while(getc(stdin) != EOF);,但解析器的行为正常,&#34; eat&#34;每个字符都会输入EOF

如何在不弄乱stdin的情况下收到 Ctrl 信号?

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

static void nsh_signal_handler(int code)
{
    char c;

    switch(code)
    {
        case SIGQUIT: c = '\\'; break;
    }

    fprintf(stdout, "I will do nothing about your Ctrl - %c\n", c);
}

int main(void)
{
    int c;
    struct sigaction s;

    s.sa_flags = 0;
    s.sa_handler = nsh_signal_handler;
    sigfillset(&s.sa_mask);
    sigaction(SIGQUIT, &s, NULL);

    do
    {
        c = getc(stdin);
        printf("[%c][%d]\n", c, c);
    }
    while(c != EOF);

    return 0;
}

上面的代码显示了此错误。

2 个答案:

答案 0 :(得分:1)

对于文件的真正结束或错误情况,getc调用将返回EOF

如果您需要区分这两者,可以使用feofferror来执行此操作。

对于您的特定情况,您可以简单地替换:

while(c != EOF);

使用:

while ((c != EOF) || (! feof(stdin)));

或许更好的是避免尝试输出字符,如果它是被信号捕获的字符。您可以通过将循环更改为:

来完成此操作
do {
    c = getc(stdin);
    while ((c == EOF) && (!feof(stdin))) { // throw away CTRL-whatever.
        //clearerr (stdin);
        c = getc(stdin);
    }
    printf("[%c][%d]\n", c, c);            // print true characters and last EOF.
}
while (c != EOF);

您会注意到上面代码中有clearerr号注释。如果您的实现是在您清除错误标志(Linux不是其中之一)之前将持续提供错误指示的实现之一,您可能希望取消注释,特别是因为它不应该损害代码流。

我实际上认为这种行为可能违反标准,因为它具体说明:

  

如果设置了流的文件结束指示符,或者流位于文件结尾,则设置流的endoffile指示符并且fgetc函数返回EOF。 否则,fgetc函数返回stream指向的输入流中的下一个字符。 如果发生读取错误,则设置流的错误指示符并设置fgetc函数返回EOF。

换句话说, no 提到了前面的错误指示符,阻止了将来的读取。我能看到被允许的唯一方法是,如果文本“发生读取错误”包括事件“先前已发生读取错误并且错误指示器未被重置”,这对我来说似乎有点紧张。 / p>

答案 1 :(得分:0)

如果您不想在处理信号后处理读取调用的错误,可以在信号处理程序上设置SA_RESTART标志:

s.sa_flags = SA_RESTART;

这将导致getc调用不会被信号处理程序的EINTR错误中断。