c-Ctrl信号用EOF填充stdin



我正在做一个解析器,获取字符直到EOF,我正在处理信号SIGTERMSIGINTSIGTSTPSIGQUIT。因此,当我用Ctrl+C(例如发送给SIGINT)发送信号时,信号处理程序会打印+C,然后必须继续,但不会继续。

我发现,在每个Ctrl信号之后,一个EOF正在填充缓冲区,但我不知道如何消除它。我试图在处理程序中执行while(getc(stdin) != EOF);,但解析器表现正常,"吃掉"所有键入的字符,直到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 - %cn", 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;
}

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

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不是其中之一),那么您可能需要取消注释它,特别是因为它不应该损害代码流。

事实上,我认为这种行为可能违反了标准,因为它特别指出:

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

换句话说,没有提及防止未来读取的先前错误指示器。我唯一能看到允许的方式是,如果文本"发生读取错误"包括事件"以前发生过读取错误,错误指示器没有重置",这对我来说似乎有点牵强。

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

s.sa_flags = SA_RESTART;

这将导致CCD_ 17调用不会被信号处理器的CCD_。

最新更新