diff mbox series

malloc: Smoke test for libmemusage

Message ID 878qyb2f2w.fsf@oldenburg.str.redhat.com
State New
Headers show
Series malloc: Smoke test for libmemusage | expand

Commit Message

Florian Weimer July 9, 2024, 7:35 a.m. UTC
It was reported that libmemusage stopped working due to the
changes in commit aaad2123d68275acc0f061e ("elf: Fix slow tls
access after dlopen [BZ #19924]").  This shared object uses
non-static TLS and interposes malloc, so it runs into the
recursion issue worked around in commit 018f0fc3b818d4d1460a
("elf: Support recursive use of dynamic TLS in interposed
malloc") with certain applications.  While the test added here
does not detect the recu issue, it is better than no test
at all.

---
 malloc/Makefile       | 16 ++++++++++-
 malloc/tst-memusage.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 1 deletion(-)


base-commit: 4c09bd400b689f1af8e08103cff3d25e0cba51d4
diff mbox series

Patch

diff --git a/malloc/Makefile b/malloc/Makefile
index 02aff1bd1d..b623c33bd0 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -54,6 +54,7 @@  tests := \
   tst-memalign \
   tst-memalign-2 \
   tst-memalign-3 \
+  tst-memusage \
   tst-obstack \
   tst-posix_memalign \
   tst-pvalloc \
@@ -279,8 +280,13 @@  extra-objs += memusagestat.o
 # kernel interface headers, not something like libgd.  So the simplest thing
 # is to presume that the standard system headers will be ok for this file.
 $(objpfx)memusagestat.o: sysincludes = # nothing
+
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)/tst-memusage-stat.out
 endif
-endif
+
+endif # $(LIBGD)
+endif # !$(cross-compiling)
 
 # Another goal which can be used to override the configure decision.
 .PHONY: do-memusagestat
@@ -419,3 +425,11 @@  $(objpfx)tst-malloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
 
 tst-aligned-alloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
 tst-malloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+
+tst-memusage-ENV = LD_PRELOAD=$(objpfx)/libmemusage.so \
+  MEMUSAGE_OUTPUT=$(objpfx)/tst-memusage-output.data
+$(objpfx)tst-memusage: $(objpfx)/libmemusage.so
+$(objpfx)tst-memusage-stat.out: $(objpfx)tst-memusage.out $(objpfx)memusagestat
+	$(test-wrapper-env) $(run-program-env) $(rtld-prefix) \
+	  $(objpfx)memusagestat $(objpfx)/tst-memusage-output.data >$@ 2>&1; \
+	$(evaluate-test)
diff --git a/malloc/tst-memusage.c b/malloc/tst-memusage.c
new file mode 100644
index 0000000000..dc9de8f85a
--- /dev/null
+++ b/malloc/tst-memusage.c
@@ -0,0 +1,75 @@ 
+/* Smoke test for libmemusagestat.so.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* Do not use the test driver because this test needs to avoid
+   forking, to avoid exercising fork handling in libmemusage.  */
+
+#include <array_length.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/xthread.h>
+#include <unistd.h>
+
+static void *allocations[1000];
+static unsigned int allocations_count;
+
+static void
+record (void *ptr)
+{
+  if (ptr == NULL)
+    FAIL_EXIT1 ("memory allocation failure");
+  if (allocations_count < array_length (allocations))
+    allocations[allocations_count++] = ptr;
+  else
+    FAIL_EXIT1 ("out of space for pointer tracking");
+}
+
+static void
+free_all (void)
+{
+  for (unsigned int i = 0; i < allocations_count; ++i)
+    free (allocations[i]);
+  allocations_count = 0;
+}
+
+static void *
+perform_allocations (void *ignored)
+{
+  for (int loops = 0; loops < 3; ++loops)
+    {
+      for (int i = 0; i < array_length (allocations); ++i)
+        record (malloc (1000));
+      free_all ();
+      for (int i = 0; i < array_length (allocations); ++i)
+        record (calloc (1000, 2));
+      free_all ();
+      for (int i = 0; i < array_length (allocations); ++i)
+        record (realloc (NULL, 4000));
+      free_all ();
+    }
+  return NULL;
+}
+
+int
+main (void)
+{
+  perform_allocations (NULL);
+  xpthread_join (xpthread_create (NULL, perform_allocations, NULL));
+}