c - 奇怪的 sigaction() 和 getline() 交互

标签 c signals getline signal-handling

我使用 sigaction 设置了一个信号处理程序,如下所示:

struct sigaction act, oldact;
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = sig_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGALRM);
sigaddset(&act.sa_mask, SIGINT);
sigaddset(&act.sa_mask, SIGTERM);
sigaddset(&act.sa_mask, SIGTSTP);
sigaction(SIGALRM, &act, &oldact);
sigaction(SIGINT, &act, &oldact);
sigaction(SIGTERM, &act, &oldact);
sigaction(SIGTSTP, &act, &oldact);
act.sa_flags = 0;

然后我运行一个 for 循环来收集输入并将其打印出来(基本上就像猫一样)。

char *linebuf = NULL;
size_t n = 0;
int len;
while(1){
    len = getline(&linebuf, &n, stdin);
    if(len>0){
        printf("%s", linebuf);
    }
}

但是,一旦我从处理信号返回,getline()不再阻塞输入,而是始终返回 -1在设置 errno 时至 EINTR这是一个中断的系统调用。我显然打算打断getline() ,但如何重置它以便我可以继续阅读输入?

有几个类似的问题并没有真正解决我的问题,但它可能会帮助您更好地理解问题。 1 2

另一个有趣的消息是我在使用 signal() 时没有遇到这个问题。用于我的信号处理,但我改为 sigaction()因为它符合 POSIX。

最佳答案

一个很晚的答案,但我会分享我最近在处理这个问题时学到的一些东西。当您在 sigaction 结构中将 sa_flags 设置为 0 时,您清除了获取信号时读取的默认行为。当您使用旧的 signal() 方法时,会保留此默认行为。要在您的情况下恢复此状态,您必须设置 sa_flags = SA_RESTART。但在这种情况下,将调用信号处理程序,如果 getline 不在读取过程中,它将继续等待输入。如果信号发生在读取的中间,您仍然会得到 -1,并且您必须在恢复之前清除()流。但是如果读取被阻塞等待数据并且信号发生,使用 SA_RESTART,您可以在信号处理程序成功执行后立即返回读取。

我个人希望能够中断 getline(),这样我就可以很好地终止等待管道的程序,但遇到了麻烦,因为我使用了旧的 signal() 方法来设置我的处理程序。所以我会收到信号,但 getline 永远不会被中断,因为读取被阻塞等待数据,它只会在我的信号处理程序执行后自动重新启动读取。当我移动到 sigaction 结构并设置 sa_flags=0 时,它中断了 getline 导致它基本上返回 EINTR,我可以向我的进程发送一个信号告诉它关闭。

我喜欢这个论坛。我数不清有多少次它帮助解决了一个棘手的问题。以为我会回馈。希望这对下一个程序员有帮助!

关于c - 奇怪的 sigaction() 和 getline() 交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19140892/

相关文章:

C MongoDB 驱动程序 - 如何添加日期?

c - 使用SIGTERM在子进程上调用kill会终止父进程,但是使用SIGKILL调用它会使父进程保持事件状态

c++ - 过滤 getline 收到的输入

c++ - fstream getline() 未处理的异常

c - 在信号处理程序上调用 fprintf() 是否安全?

c++ - 从 Istream 读取,如何先读一个字再读一整行,然后返回?

c - 文本文件转十六进制

c - (C) avcodec_receive_frame (ffmpeg) 函数总是返回 AVERROR(EAGAIN)

C程序没有给出正确的输出

python - 如何检查模型中特定字段的变化?