From 6d49eec68a35a38612230c3d5a5636ad3cd16979 Mon Sep 17 00:00:00 2001
From: Paul Cercueil <paul@crapouillou.net>
Date: Mon, 26 Apr 2021 16:39:43 +0100
Subject: [PATCH] xml: Cleanup libxml2 parser when exiting library

When libiio is unloaded (when the client program exits), cleanup libxml2
so that memory analyzer tools like Valgrind won't detect a memory leak.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
 xml.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/xml.c b/xml.c
index 34ec50e21..19e53594d 100644
--- a/xml.c
+++ b/xml.c
@@ -478,3 +478,47 @@ struct iio_context * xml_create_context_mem(const char *xml, size_t len)
 	xmlFreeDoc(doc);
 	return ctx;
 }
+
+
+static void cleanup_libxml2_stuff(void)
+{
+	/*
+	 * This function will be called only when the libiio library is
+	 * unloaded (e.g. when the program exits).
+	 *
+	 * Cleanup libxml2 so that memory analyzer tools like Valgrind won't
+	 * detect a memory leak.
+	 */
+	xmlCleanupParser();
+	xmlMemoryDump();
+}
+
+#if defined(_MSC_BUILD)
+#pragma section(".CRT$XCU", read)
+#define __CONSTRUCTOR(f, p) \
+  static void f(void); \
+  __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
+  __pragma(comment(linker,"/include:" p #f "_")) \
+  static void f(void)
+#ifdef _WIN64
+#define _CONSTRUCTOR(f) __CONSTRUCTOR(f, "")
+#else
+#define _CONSTRUCTOR(f) __CONSTRUCTOR(f, "_")
+#endif
+#elif defined(__GNUC__)
+#define _CONSTRUCTOR(f) static void __attribute__((constructor)) f(void)
+#else
+#define _CONSTRUCTOR(f) static void f(void)
+#endif
+
+_CONSTRUCTOR(initialize)
+{
+	/*
+	 * When the library loads, register our destructor.
+	 * Do it here and not in the context creation function,
+	 * as it could otherwise end up registering the destructor
+	 * many times.
+	 */
+	atexit(cleanup_libxml2_stuff);
+}
+#undef _CONSTRUCTOR