Hello Pixmen,

I wish to use libpixman.so with my (C code) loadable DSO (dynamic shared
object) library
modules.  I wrote a patch that fixes libpixman.so so that memory allocated
in the pixman
library constructor is freed in a (newly added) library destructor
function.  When I unload
the last module that depends on libpixman.so I get a memory leak without
the attached
patch.

The attached patch is only 29 lines (total) over 2 files.

I tested it on git commit ffa5645a2d139106a9154406e3b413fad14fe588  HEAD
master
from https://gitlab.freedesktop.org/pixman/pixman


FOOD FOR THOUGHT (i.e. verbose):
This patch fixes my needs, but one might also consider adding a
corresponding "undo-er"
function which corresponds with the get_implementation() function; but it
may be matter of
debate as to how that would be used (if at all) aside from being used in
the library
destructor function (where it sits in this patch).

I was using Valgrind.  On my computer (x86  AMD Ryzen 7) libpixman.so made
6 unfreed
malloc() allocations (which the patch fixes).  I can provide test scripts
if requested.  Currently
my test scripts are integrated in the software package I'm working on.  I
wish to write a robust
software package, and hence, that requires that dependency libraries also
be robust (or
whatever you want to call it).


cheers
lance
diff --git a/meson.build b/meson.build
index 3b56f4f..8ca8796 100644
--- a/meson.build
+++ b/meson.build
@@ -519,6 +519,15 @@ if cc.links('''
   config.set('TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR', 1)
 endif
 
+if cc.links('''
+    static int x = 1;
+    static void __attribute__((destructor)) destructor_function () { x = 0; }
+    int main (void) { return x; }
+    ''',
+    name : '__attribute__((destructor))')
+  config.set('TOOLCHAIN_SUPPORTS_ATTRIBUTE_DESTRUCTOR', 1)
+endif
+
 if cc.links(
     ' __float128 a = 1.0Q, b = 2.0Q; int main (void) { return a + b; }',
     name : 'Has float128 support')
diff --git a/pixman/pixman.c b/pixman/pixman.c
index 82ec236..936680c 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -40,6 +40,24 @@ pixman_constructor (void)
 }
 #endif
 
+#ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_DESTRUCTOR
+// This will work even if there is no constructor.
+static void __attribute__((destructor))
+pixman_destructor (void)
+{
+    pixman_implementation_t *d;
+
+    // Free all implementations that are in the list, if there are any:
+    for(d = global_implementation; d;)
+    {
+        pixman_implementation_t *level;
+        level = d; // save this one to free
+        d = d->fallback; // go to next one if there is one
+        free (level); // free the one before
+    }
+}
+#endif
+
 typedef struct operator_info_t operator_info_t;
 
 struct operator_info_t

Reply via email to