[Libevent-users] fixes for mem leaks etc

Phil Oleson oz at nixil.net
Thu Jan 25 15:28:45 EST 2007


Niels,

	My company recently licensed Coverity Prevent for internal use, and
since we used libevent in at least 1-2 apps, I thought I'd check out libevent.
It found a couple memory leaks in http.c and evrpc.c, and a possible
FORWARD_NULL issue (which I fixed, though it's debatable if it would actually
ever pop up).  I've also included the C++ fix to evdns.h as it's not been
commited to Subversion yet.

Patches attached.

	-Phil.
-------------- next part --------------
Index: evdns.h
===================================================================
--- evdns.h	(revision 312)
+++ evdns.h	(working copy)
@@ -237,6 +237,10 @@
 #ifndef EVENTDNS_H
 #define EVENTDNS_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Error codes 0-5 are as described in RFC 1035. */
 #define DNS_ERR_NONE 0
 /* The name server was unable to interpret the query */
@@ -303,4 +307,8 @@
 
 #define DNS_NO_SEARCH 1
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  // !EVENTDNS_H
-------------- next part --------------
Index: event.c
===================================================================
--- event.c	(revision 312)
+++ event.c	(working copy)
@@ -301,6 +301,8 @@
 		}
 	}
 
+	if (!activeq) return;
+
 	for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) {
 		event_queue_remove(base, ev, EVLIST_ACTIVE);
 		
-------------- next part --------------
Index: evrpc.c
===================================================================
--- evrpc.c	(revision 312)
+++ evrpc.c	(working copy)
@@ -260,19 +260,25 @@
 void
 evrpc_pool_free(struct evrpc_pool *pool)
 {
-	struct evhttp_connection *connection;
-	struct evrpc_request_wrapper *request;
+	struct evhttp_connection *connection, *conn_next;
+	struct evrpc_request_wrapper *request, *req_next;
 
-	while ((request = TAILQ_FIRST(&pool->requests)) != NULL) {
-		TAILQ_REMOVE(&pool->requests, request, next);
+	request = TAILQ_FIRST(&pool->requests);
+	while (request != NULL) {
+		req_next = TAILQ_NEXT(request, next);
 		/* if this gets more complicated we need our own function */
 		evrpc_request_wrapper_free(request);
+		request = req_next;
 	}
+	TAILQ_INIT(&pool->requests);
 
-	while ((connection = TAILQ_FIRST(&pool->connections)) != NULL) {
-		TAILQ_REMOVE(&pool->connections, connection, next);
+	connection = TAILQ_FIRST(&pool->connections);
+	while (connection != NULL) {
+		conn_next = TAILQ_NEXT(connection, next);
 		evhttp_connection_free(connection);
+		connection = conn_next;
 	}
+	TAILQ_INIT(&pool->connections);
 
 	free(pool);
 }
-------------- next part --------------
Index: http.c
===================================================================
--- http.c	(revision 312)
+++ http.c	(working copy)
@@ -715,7 +715,7 @@
 void
 evhttp_connection_free(struct evhttp_connection *evcon)
 {
-	struct evhttp_request *req;
+	struct evhttp_request *req, *next_req;
 
 	/* notify interested parties that this connection is going down */
 	if (evcon->fd != -1) {
@@ -724,10 +724,13 @@
 	}
 
 	/* remove all requests that might be queued on this connection */
-	while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
-		TAILQ_REMOVE(&evcon->requests, req, next);
+	req = TAILQ_FIRST(&evcon->requests);
+	while (req != NULL) {
+		next_req = TAILQ_NEXT(req, next);
 		evhttp_request_free(req);
+		req = next_req;
 	}
+	TAILQ_INIT(&evcon->requests);
 
 	if (evcon->http_server != NULL) {
 		struct evhttp *http = evcon->http_server;
@@ -1021,16 +1024,17 @@
 void
 evhttp_clear_headers(struct evkeyvalq *headers)
 {
-	struct evkeyval *header;
+	struct evkeyval *header, *next_head;
 
-	for (header = TAILQ_FIRST(headers);
-	    header != NULL;
-	    header = TAILQ_FIRST(headers)) {
-		TAILQ_REMOVE(headers, header, next);
+	header = TAILQ_FIRST(headers);
+	while (header != NULL) {
+		next_head = TAILQ_NEXT(header, next);
 		free(header->key);
 		free(header->value);
 		free(header);
+		header = next_head;
 	}
+	TAILQ_INIT(headers);
 }
 
 /*
@@ -1863,25 +1867,30 @@
 void
 evhttp_free(struct evhttp* http)
 {
-	struct evhttp_cb *http_cb;
-	struct evhttp_connection *evcon;
+	struct evhttp_cb *http_cb, *cb_next;
+	struct evhttp_connection *evcon, *evcon_next;
 	int fd = http->bind_ev.ev_fd;
 
 	/* Remove the accepting part */
 	event_del(&http->bind_ev);
 	close(fd);
 
-	while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
-		/* evhttp_connection_free removes the connection */
-		evhttp_connection_free(evcon);
+	evcon = TAILQ_FIRST(&http->connections);
+	while (evcon != NULL) {
+		evcon_next = TAILQ_NEXT(evcon, next);
+		evhttp_connection_free(evcon);	/* removes the connection */
+		evcon = evcon_next;
 	}
 
-	while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
-		TAILQ_REMOVE(&http->callbacks, http_cb, next);
+	http_cb = TAILQ_FIRST(&http->callbacks);
+	while (http_cb != NULL) {
+		cb_next = TAILQ_NEXT(http_cb, next);
 		free(http_cb->what);
 		free(http_cb);
+		http_cb = cb_next;
 	}
-	
+	TAILQ_INIT(&http->callbacks);
+
 	free(http);
 }
 


More information about the Libevent-users mailing list