我正在使用解析器获取字符EOF
,我处理信号SIGTERM
,SIGINT
,SIGTSTP
和SIGQUIT
。所以当我用 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;
}
上面的代码显示了此错误。
答案 0 :(得分:1)
对于文件的真正结束或错误情况,getc
调用将返回EOF
。
如果您需要区分这两者,可以使用feof
或ferror
来执行此操作。
对于您的特定情况,您可以简单地替换:
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
错误中断。