libevent/libevent — pull request #182 by JohnOhl (2014-10-26 05:56:00+00:00)
Title: Feature: Auto-free an evhttp_connection when requests have completed

I've spent quite a bit of time trying to come up with efficient methods for cleaning up outbound evhttp connections since they cannot be freed from any existing callbacks without causing a segfault. It can be quite difficult to ensure an evhttp_connection object is free'd appropriately (without having to re-queue a special event onto a base event, i.e. my sample in https://github.com/libevent/libevent/issues/115) while avoiding race conditions.

In the end we came up /w a simple interface for telling libevent to automatically free an outbound evhttp connection after it's last request has finished, making management of many fire and forget requests/connections much simpler. I thought I'd put this out here to gather some feedback and to see if anyone else finds it useful or has any suggestions/input, etc.

To use it, create an evhttp connection object and call `evhttp_connection_free_on_completion` on it anytime before the base is dispatched or if adding the connection to an already running base (from another thread for example), call it before adding the first request.

Once the last request/retry has been executed and all of the callbacks have finished, the connection will be freed automatically.

Example (original taken from: http://www.ideawu.com/blog/2013/09/libevent-http-client-example.html)

```
#include
#include
#include
#include
#include
#include
#include
#include

void http_request_done(struct evhttp_request *req, void *arg){
char buf[1024];
int s = evbuffer_remove(req->input_buffer, &buf, sizeof(buf) - 1);
buf[s] = '\0';
printf("%s", buf);
// terminate event_base_dispatch()
event_base_loopbreak((struct event_base *)arg);
}

int main(int argc, char **argv){
struct event_base *base;
struct evhttp_connection *conn;
struct evhttp_request *req;

base = event_base_new();
conn = evhttp_connection_base_new(base, NULL, "127.0.0.1", 8080);
req = evhttp_request_new(http_request_done, base);

/* Tell libevent to free the connection when the request finishes */
evhttp_connection_free_on_completion(conn);

evhttp_add_header(req->output_headers, "Host", "localhost");
//evhttp_add_header(req->output_headers, "Connection", "close");

evhttp_make_request(conn, req, EVHTTP_REQ_GET, "/index.php?id=1");
evhttp_connection_set_timeout(req->evcon, 600);
event_base_dispatch(base);

return 0;
}
```