如何以正确的方式使用libevent的信号事件



libevent支持在观察信号到达时通知。看来这些信号可以在Linux/unix上的任何地方中断(>是正确的吗?)。这是否意味着我应该检查返回值,而调用所有系统调用和其他库功能后,errno是相等的EINTR?有简单的测试代码。

#include <stdio.h>
#include <signal.h>
int i = 0;
void handle(int signo)
{
    printf("i[%d], signo[%d]n", i, signo);
}
int main()
{
    signal(SIGINT, handle);
    while (1) {
        i++;
    }   
    return 0;
}

运行此代码后,然后按几个 ctrl C ,获取以下输出:

 ./signal 
^Ci[475151517], signo[2]
^Ci[656118185], signo[2]
^Ci[891673397], signo[2]
^Ci[1668347228], signo[2]
^Ci[-2123628990], signo[2]

看来siginti++中断。如果上述猜想是正确的,那是处理这样的信号的正确方法:

  • 调用pthread_sigmask在运行事件循环的主线程中阻止信号。
  • 呼叫sigwait在监视线程中等待信号,并通过管道通知主线程。

谢谢!

是的,信号可以在任何地方中断执行(除非蒙版),并且是的,这意味着所有系统调用(我不确定是否有一些例外?),例如写入/读取/当被信号中断时,民意调查将返回EINT(您可能需要阅读PSELECT的MAN页面,尤其是"错误"部分)。这被称为" PC失败者问题"

您应该使用libevent本机支持进行信号处理。在其文档中查看所有宏" evsignal_xxx"。

简而言之,您会做这样的事情:

struct event ev_sigint;
struct event_base *ev_base;
ev_base = event_init();
evsignal_set(&ev_sigint, SIGINT, sighandler, ev_base);
evsignal_add(&ev_sigint, NULL);
event_dispatch();

然后从信号处理程序中打破循环:

void sighandler(int signal, short events, void *base)
{
    event_base_loopbreak(base);
}

最新更新