Attached is a patch to configure libevent so that it uses pluto's
leak-detective.  It does throw up some leaks but they are mostly
harmless - pluto just needs to execute:
+       dbg("releasing event base");
+       event_base_free(pluto_eb);
+       pluto_eb = NULL;
+       dbg("releasing global event data");
+       /* this releases data allocated by evthread_use_pthreads() */
+       libevent_global_shutdown();
as part of a clean shutdown.  The attached patch also adds these missing calls.

I'm going to sit on this for now (I need to test more than just
ikev2-12-x509-ikev1-rw), but that can wait until later.

Andrew

PS: more surprisingly is that this patch and count-pointers.awk found
a bug in leak-detective :-)
commit f4c519e61129446dbe833115d5b6ecfc5b73b87a
Author: Andrew Cagney <[email protected]>
Date:   Fri Mar 22 10:50:34 2019 -0400

    events: point libevent at pluto's memory allocator; free libevent's resources during exit

diff --git a/include/lswalloc.h b/include/lswalloc.h
index 532bda451c..268a337ef2 100644
--- a/include/lswalloc.h
+++ b/include/lswalloc.h
@@ -29,6 +29,7 @@ extern void pfree(void *ptr);
 extern void *alloc_bytes(size_t size, const char *name);
 extern void *clone_bytes(const void *orig, size_t size,
 			  const char *name);
+void resize_bytes(void **ptr, size_t new_size);
 
 extern bool leak_detective;
 extern void report_leaks(void);
diff --git a/lib/libswan/alloc.c b/lib/libswan/alloc.c
index e988e055a5..9c616e4cf7 100644
--- a/lib/libswan/alloc.c
+++ b/lib/libswan/alloc.c
@@ -219,3 +219,30 @@ void *clone_bytes(const void *orig, size_t size, const char *name)
 	memcpy(p, orig, size);
 	return p;
 }
+
+/*
+ * Re-size something on the HEAP.
+ *
+ * Unlike the more traditional realloc() this code doesn't allow a
+ * NULL pointer.  The caller, which is presumably implementing some
+ * sort of realloc() wrapper, gets to handle this.  So as to avoid any
+ * confusion, give this a different name and function signature.
+ *
+ * Efficiency isn't this code's strong point.
+ */
+
+void resize_bytes(void **ptr, size_t new_size)
+{
+	void *old = *ptr;
+	passert(old != NULL);
+	if (leak_detective) {
+		const union mhdr *p = ((const union mhdr *)old) - 1;
+		passert(p->i.magic == LEAK_MAGIC);
+		void *new = alloc_bytes_raw(new_size, p->i.name);
+		memcpy(new, old, min(p->i.size, new_size));
+		pfree(old);
+		*ptr = new;
+	} else {
+		*ptr = realloc(old, new_size);
+	}
+}
diff --git a/programs/pluto/server.c b/programs/pluto/server.c
index 8183cc305b..4890262be0 100644
--- a/programs/pluto/server.c
+++ b/programs/pluto/server.c
@@ -442,7 +442,12 @@ void free_pluto_event_list(void)
 	struct pluto_event **head = &pluto_events_head;
 	while (*head != NULL)
 		*head = free_event_entry(head);
-
+	dbg("releasing event base");
+	event_base_free(pluto_eb);
+	pluto_eb = NULL;
+	dbg("releasing global event data");
+	/* this releases data allocated by evthread_use_pthreads() */
+	libevent_global_shutdown();
 }
 
 void link_pluto_event_list(struct pluto_event *e) {
@@ -962,7 +967,46 @@ static void childhandler_cb(int unused UNUSED, const short event UNUSED, void *a
 	}
 }
 
-void init_event_base(void) {
+#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
+static void *libevent_malloc(size_t size)
+{
+	void *ptr = alloc_bytes(size, __func__);
+	dbg("%s: new ptr-libevent@%p size %zu", __func__, ptr, size);
+	return ptr;
+}
+static void *libevent_realloc(void *ptr, size_t size)
+{
+	if (ptr == NULL) {
+		ptr = alloc_bytes(size, __func__);
+		dbg("%s: new ptr-libevent@%p size %zu", __func__, ptr, size);
+		return ptr;
+	} else {
+		/* enough to keep count-pointers.awk happy */
+		dbg("%s: release ptr-libevent@%p", __func__, ptr);
+		resize_bytes(&ptr, size);
+		dbg("%s: new ptr-libevent@%p size %zu", __func__, ptr, size);
+		return ptr;
+	}
+}
+static void libevent_free(void *ptr)
+{
+	dbg("%s: release ptr-libevent@%p", __func__, ptr);
+	pfree(ptr);
+}
+#endif
+
+void init_event_base(void)
+{
+	/*
+	 * "... if you are going to call this function, you should do
+	 * so before any call to any Libevent function that does
+	 * allocation."
+	 */
+#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
+	dbg("pointing libevent at pluto's memory allocator");
+	event_set_mem_functions(libevent_malloc, libevent_realloc,
+				libevent_free);
+#endif
 	libreswan_log("Initializing libevent in pthreads mode: headers: %s (%" PRIx32 "); library: %s (%" PRIx32 ")",
 		      LIBEVENT_VERSION, (ev_uint32_t)LIBEVENT_VERSION_NUMBER,
 		      event_get_version(), event_get_version_number());
@@ -973,10 +1017,12 @@ void init_event_base(void) {
 	int r = evthread_use_pthreads();
 	passert(r >= 0);
 	/* now do anything */
+	dbg("creating event base");
 	pluto_eb = event_base_new();
 	passert(pluto_eb != NULL);
 	int s = evthread_make_base_notifiable(pluto_eb);
 	passert(s >= 0);
+	dbg("libevent initialized");
 }
 
 /* call_server listens for incoming ISAKMP packets and Whack messages,
_______________________________________________
Swan-dev mailing list
[email protected]
https://lists.libreswan.org/mailman/listinfo/swan-dev

Reply via email to