/* Copyright (C) 2020 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 . */ /* This test checks that leakage does not happen from repeated loads of a module with TLS. */ #include #include #include #include int (*tlsmod_fun) (void); /* Async-signal-safe TLS space is gotten via custom allocator using mmap(), so it doesn't work to use functions like mtrace() or mallinfo(). */ size_t get_vm_size (void) { long result; FILE *f = fopen ("/proc/self/statm", "r"); if (!f) { fprintf (stderr, "get_vm_size could not open /proc/self/statm\n"); return 0; } if (fscanf (f, "%lu", &result) != 1) { fprintf (stderr, "get_vm_size failed to read size\n"); return 0; } if (fclose (f) != 0) { fprintf (stderr, "get_vm_size fclose failed\n"); return 0; } return (size_t) result; } int do_test (void) { int count = 0; size_t start_size = get_vm_size (); if (start_size == 0) { puts ("Cannot get vm size, test cannot run"); exit (0); } /* Open, use, and close a shared library repeatedly. */ for (int i = 0; i < 1000; ++i) { void *h = dlopen ("tst-tls7leakmod.so", RTLD_NOW); if (h == NULL) { puts ("dlopen failed"); exit (1); } tlsmod_fun = dlsym (h, "module_fun"); if (tlsmod_fun == NULL) { puts ("dlsym for module_fun failed"); exit (1); } count += tlsmod_fun (); /* Don't leave dangling pointer after dlclose. */ tlsmod_fun = NULL; if (dlclose (h)) { puts ("dlclose failed"); exit (1); } } size_t end_size = get_vm_size (); printf ("VM usage went from %ld to %ld pages", start_size, end_size); /* Allow for some growth in usage. */ if ((end_size - start_size) > 10) { printf (", which indicates a leak in TLS allocation\n"); return 1; } else { printf (", which is acceptable\n"); return 0; } } #define TIMEOUT 8 #define TEST_FUNCTION do_test () #include "../test-skeleton.c"