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]
看来sigint
在i++
中断。如果上述猜想是正确的,那是处理这样的信号的正确方法:
- 调用
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);
}