之前一直使用libevent 信号注册事件函数:evsignal_new() 进行信号事件注册。然后也一直都很正常,但是有一次,这个函数也一样的使用,结果发送信号时,回调函数却没有被调用。与之前的代码进行对比,却没有任何不一样的地方。苦恼了好久,终于在今天花了几个小时的时间找到了这个问题的解决方法。
只要在evsignal_new() 函数调用成功之后,再调用event_add() 函数,即可。
虽然是这里处理好了,却给了我另一个疑问了,如果这个真的是原因的话,那么为什么我在别的地方(之前代码正常触发信号事件回调函数)并没有调用这个函数进行添加这个事件,却能够很好的触发信号回调函数呢?呵呵,先留着这个疑问吧,当然,如果有人知道答案的话还忘你留言给我。
有问题的代码:
#include "start.h"
#include <string.h>
#include <errno.h>
#include <signal.h>
#ifdef WIN32
# include <WinSock2.h>
#else
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
# include <arpa/inet.h>
# endif
#include <sys/socket.h>
#endif
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>
#define LOG_LOGIN_ERR std::cerr << "[login_server Error]: "
#define LOG_LOGIN_INFO std::cout << "[login_server Info]: "
#define LOG_LOGIN_DBG std::cout << "[login_server Debug]: "
static const char * const LOGIN_LISTEN_CLT_IP = "192.168.230.128";
static const short LOGIN_LISTEN_CLT_PORT = 9105;
static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
struct sockaddr *sa, int socklen, void *user_data);
static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
struct sockaddr *sa, int socklen, void *user_data)
{
LOG_LOGIN_INFO << "连接的回调函数." << std::endl;
}
static void signal_cb(evutil_socket_t sig, short events, void *user_data);
static void signal_cb(evutil_socket_t sig, short events, void *user_data)
{
LOG_LOGIN_INFO << "信号发生了,回调函数." << std::endl;
}
void start()
{
struct event_base *struBase = event_base_new();
if (struBase == NULL)
{
LOG_LOGIN_ERR << "Could not initialize libevent!" << std::endl;
return ;
}
// 准备服务器地址
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(LOGIN_LISTEN_CLT_PORT);
int res = inet_pton(AF_INET, LOGIN_LISTEN_CLT_IP, &sin.sin_addr);
if (!res)
{
LOG_LOGIN_ERR << "inet_pton() " << strerror(errno) << std::endl;
event_base_free(struBase), struBase = NULL;
return ;
}
// 创建监听器
struct evconnlistener *listener = evconnlistener_new_bind(
struBase, listener_cb, NULL,
LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
-1, (struct sockaddr *)&sin, sizeof(sin) );
if (listener == NULL)
{
LOG_LOGIN_ERR << "Could not create listener!" << std::endl;
event_base_free(struBase), struBase = NULL;
return ;
}
// 注册信号事件
struct event *signal_event = evsignal_new(
struBase, SIGINT, signal_cb, (void *)struBase);
if (signal_event == NULL)
{
LOG_LOGIN_ERR << "Could not create/add a signal event." << std::endl;
evconnlistener_free(listener), listener = NULL;
event_base_free(struBase), struBase = NULL;
return ;
}
LOG_LOGIN_INFO << "开始事件循环." << std::endl;
event_base_dispatch(struBase);
}
这里只需要在evsignal_new() 函数调用成功之后,添加一行代码:event_add(signal_event, NULL) 即可。