libevent可以检测系统信号,我们这里以检测SIGINT为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include "common.h" #include "event_config.h" #include "event_base.h" #include "event_signal.h"
using namespace std; using namespace echo;
int two_sum(int a,int b) { std::cout<<"a + b = "<<a+b<<std::endl; return a+b; }
int main() { Callback<int>two(two_sum,10,20); auto methods = event_get_supported_methods(); std::shared_ptr<Base>bases = std::make_shared<Base>(9999,listen_callback, two); Signal s(*(bases.get()),SIGINT, two); s.signal_add(); bases->start_base_dispatch(); return 0; }
|
初始化signal类时传入基础事件上下文,要检测的信号类型,以及信号触发时的回掉函数。
以下是Signal的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #ifndef LIBEVENT_TEST_EVENT_SIGNAL_H #define LIBEVENT_TEST_EVENT_SIGNAL_H
#include "common.h"
namespace echo { class Signal { public: Signal(Base& base,int signal,Callback<int>& callback) { init_signal = evsignal_new(base.get_instance(), signal, signal_callback, (void*)&callback); error_nullptr(VNAME(init_signal), init_signal); } static void signal_add(event* signal) { error_return_value(0,VNAME(event_add), event_add,signal, nullptr); } void signal_add() { error_return_value(0,VNAME(event_add), event_add,init_signal, nullptr); } ~Signal() { free_source(event_free,init_signal); } event* get_signal() { error_nullptr(VNAME(init_signal),init_signal); return init_signal; } private: event* init_signal; }; };
#endif
|
其中evsignal_new函数为信号初始化函数,回初始化好信号的事件上下文,监听的信号,信号触发的回掉函数,以及回掉函数的参数,这里我们依然和之前一样传入包装器callback,以便调用自己的回掉函数。其中的signal_callback是原本触发的信号处理函数,但是里面我们什么也不做,只是调用我们包装器,以便达到扩展的目的。
1 2 3 4 5
| void signal_callback(int socket,short which,void* arg) { std::cout<<reinterpret_cast<Callback<int>*>(arg)->instance()<<std::endl; }
|
再往下是一个我弄的一个新的返回值处理的包装器,用于处理返回值异常的情况
1 2 3 4 5 6 7 8 9 10 11 12
| template<class V,class F,class ...Arg> inline static void error_return_value(V value,const std::string& f_name,F&& fn,Arg&&... arg)
{ if(std::invoke(std::forward<F>(fn), std::forward<Arg>(arg)...)) { std::cerr<<"return value error : "<<__FILE__<<__LINE__<<":\t"<<f_name <<"return value is not expect "<<value<<std::endl; exit(0); } }
|
资源释放依旧采用的是之前写好的指针类资源回收包装器
1 2 3 4 5 6
| template<class F,class S> inline static void free_source(F&& fn,S&& arg) { if(arg) fn(arg); arg = nullptr; }
|
回到libevent的信号注册,一个分为以下几个部分:获取监听事件上下文,注册要监听的信号,将监听信号绑定要监听的事件上,被监听的事件开始运行,相关资源的回收。