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

时间:2017-03-16 11:51:05

标签: linux multithreading signals 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等待观察线程中的信号,并通过管道通知主线程。

谢谢!

1 个答案:

答案 0 :(得分:0)

是的,一个信号可以在任何地方中断执行(除非被屏蔽),是的,它意味着所有系统调用(我不确定是否有一些例外?),例如写入/读取/轮询将在被中断时返回EINT信号(您可能想要阅读man page for pselect,特别是'BUGS'部分)。这称为'PC loser-ing problem'

您应该使用libevent原生支持进行信号处理。查看所有宏'evsignal_xxx'in their documentation

简而言之,您可以这样做:

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);
}