diff options
author | Leonid Lisovskiy <lly.dev@gmail.com> | 2016-06-20 20:29:45 +0300 |
---|---|---|
committer | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-06-22 08:02:51 +0200 |
commit | bc5949fd4f8cddf4eee74492c86a8a72f4dee0e7 (patch) | |
tree | 68cf04f3eade770ecd41bfb782bc5e9f51acbe94 /test/dlopen/nodelete1.c | |
parent | 0bc1394750885d4e4b2064aff6c48dd542c6f4b8 (diff) |
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 <lly.dev@gmail.com>
Diffstat (limited to 'test/dlopen/nodelete1.c')
-rw-r--r-- | test/dlopen/nodelete1.c | 59 |
1 files changed, 59 insertions, 0 deletions
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 <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + + +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" |