From bc5949fd4f8cddf4eee74492c86a8a72f4dee0e7 Mon Sep 17 00:00:00 2001 From: Leonid Lisovskiy Date: Mon, 20 Jun 2016 20:29:45 +0300 Subject: ldso: fix dlsym hang when reloading DSOs It can happen under certain cases that the DSO had refcount 0, but was already loaded. (NODELETE flag is set, or it is pulled in via both NEEDED dependency and explicit dlopen()). Add extra reference count for NODELETE objects, this will ensure that the reference count never drops below one. It is improved version of http://lists.busybox.net/pipermail/uclibc/2013-June/047826.html Signed-off-by: Leonid Lisovskiy --- test/dlopen/nodelete1.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 test/dlopen/nodelete1.c (limited to 'test/dlopen/nodelete1.c') diff --git a/test/dlopen/nodelete1.c b/test/dlopen/nodelete1.c new file mode 100644 index 000000000..720e37fd1 --- /dev/null +++ b/test/dlopen/nodelete1.c @@ -0,0 +1,59 @@ +#include +#include +#include + + +int fini_ran; + +#define LIBNAME1 "nodelmod1.so" + +static int +do_test (void) +{ + /* Verify ability to reload RTLD_NODELETE libraries. + */ + void *p; + + p = dlopen (LIBNAME1, RTLD_NOW); + if (p == NULL) + { + printf ("failed to load "LIBNAME1": %s\n", dlerror ()); + exit (1); + } + + if (dlclose (p) != 0) + { + puts ("failed to close "LIBNAME1""); + exit (1); + } + + p = dlopen (LIBNAME1, RTLD_LAZY); + if (p == NULL) + { + printf ("failed to load "LIBNAME1": %s\n", dlerror ()); + exit (1); + } + + if (dlclose (p) != 0) + { + puts ("failed to close "LIBNAME1""); + exit (1); + } + + p = dlopen ("nodelmod2.so", RTLD_LAZY); + if (p == NULL) + { + printf ("failed to load \"nodelmod2.so\": %s\n", dlerror ()); + exit (1); + } + if (dlclose (p) != 0) + { + puts ("failed to close \"nodelmod2.so\""); + exit (1); + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" -- cgit v1.2.3