I'm doing some work with libevent, version 2.0.22, and I'm struggling with dealing with bufferevent_free
and making sure sockets close at the right time. This is within an iOS app built with Xcode 6.4, running on iOS 8.4.
Each socket is managed by a struct bufferevent
, and I also have a data structure which keeps track of application state for that socket:
bev = bufferevent_socket_new(evbase, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_socket_connect_hostname(bev, dns_base, AF_UNSPEC, host, port_number);
struct stream_data *data = malloc(sizeof(struct stream_data));
/* initialize stream data here */
bufferevent_setcb(bev, read_cb, write_cb, event_cb, data);
In a callback from some other buffer socket, I decide I don't need the buffer I just tried to open. This happens before I get the connected callback on the bev in question. Because I created it with BEV_OPT_CLOSE_ON_FREE
, I just free it. Then I delete the data structure I'm using. Looks like this:
bufferevent_free(bev);
free(stream_data); // the data corresponding to that bev
In this case, though, the socket actually finished connecting in the meantime. So my event callback fires:
void event_cb(struct bufferevent *bev, short what, void *ctx)
{
struct stream_data *data = ctx;
// data now points to already freed memory
}
And now I've got a pointer to already freed memory. I've confirmed with debugger breakpoints, NSLog
, etc that the event callback is firing after the free
above.
Is this expected behavior? If so, how can I ever tell that a bufferevent I freed is well and truly gone, making it safe to remove my own data structures?
答案 0 :(得分:1)
是的,这是预期的libevent行为:在bufferevent_free()之后它仍然可以调用你的回调。来自libevent书:
Bufferevents是内部引用计数的,因此如果bufferevent在释放时有挂起的延迟回调,则在回调完成之前不会删除它。
最简单的解决方案是在释放bufferevent对象之前删除所有回调:
bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
bufferevent_free(bev);