libevent源码深度剖析十三——libevent信号处理注意点

时间:2022-03-22 00:14:08

libevent源码深度剖析十三

——libevent信号处理注意点

前面讲到了libevent实现多线程的方法,然而在多线程的环境中注册信号事件,还是有一些情况需要小心处理,那就是不能在多个libevent实例上注册信号事件。依然冠名追加到libevent系列。

 

2个线程为例,做简单的场景分析。

1 首先是创建并初始化线程1libevent实例base1,线程1libevent实例base2

2 base1上注册SIGALRM信号;在base2上注册SIGINT信号;

3 假设当前base1base2上都没有注册其他的事件;

4 线程12都进入event_base_loop事件循环:

event_base_loop(base1)                                    event_base_loop(base2)

{                                                                         {

if (base2->sig.ev_signal_added)                        if (base2->sig.ev_signal_added)

evsignal_base = base1;                                 evsignal_base = base2;

while(!done)                                                       while(!done)

{                                                                           {

                                                                                …

     evsel->dispatch(…);                                              evsel->dispatch(…);

                                                                              

}                                                                         }

}                                                                           }

5 假设线程1先进入event_base_loop,并设置evsignal_base = base1;并等待;

6 接着线程2也进入event_base_loop,并设置evsignal_base = base2;并等待;

  于是evsignal_base就指向了base2

7 信号ALARM触发,调用服务例程:

static void evsignal_handler(int sig)

{

       ...

       evsignal_base->sig.evsigcaught[sig]++;

       evsignal_base->sig.evsignal_caught= 1;

       /*Wake up our notification mechanism */

       send(evsignal_base->sig.ev_signal_pair[0],"a", 1, 0);

       ...

}

于是base2得到通知ALARM信号发生了,而实际上ALARM是注册在base1上的,base2上的ALARM注册event是空的,于是处理函数将不能得到调用;

 

因此在libevent中,如果需要处理信号,只能将信号注册到一个libevent实例上。

memcached就没有使用libevent提供的signal接口,而是直接使用系统提供的原生API,看起来这样更简洁。