Knowing that all callbacks work with libevent and bufferevent_free

I am doing some work with libevent, version 2.0.22 and I am afraid to work with bufferevent_free

and make sure the sockets are closed at the right time. This is an iOS app built with Xcode 6.4, running on iOS 8.4.

Each socket is managed struct bufferevent

, and I also have a data structure that keeps track of the 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 another buffer, I decided that I didn't need the buffer I was just trying to open. This happens before I get the associated callback on the bev in question. Since I created it with BEV_OPT_CLOSE_ON_FREE

, I will just free it. Then I remove the data structure that I am using. Looks like that:

bufferevent_free(bev);
free(stream_data); // the data corresponding to that bev

      

In this case, however, the socket has actually completed the connection 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 have a pointer to the already freed memory. I have confirmed with debugger breakpoints NSLog

etc. that the event callback is fired after the free

above.

Is this the expected behavior? If so, how can I tell the freed bufferist is good and really gone, making it safe to delete my own data structures?

+3


source to share


1 answer


Yes, this is the expected behavior of libevent: after bufferevent_free (), it can still call your callbacks. From the book on freedom:

Bufferevents are internally counted by reference, so if the buffer has pending pending callbacks when it is released, it will not be removed until the callbacks have completed.



The simplest solutions are to remove all callbacks before freeing the bufferevent object:

bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
bufferevent_free(bev);

      

+1


source







All Articles