malloc: Smoke test for libmemusage

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

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed

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
  

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));
+}