On 27 June 2013 21:07:38 Timo Teras <timo.te...@iki.fi> wrote:
On Thu, 27 Jun 2013 20:36:44 +0200
"Bernhard Reutner-Fischer" <rep.dot....@gmail.com> wrote:

> On 27 June 2013 20:16:26 Rich Felker <dal...@aerifal.cx> wrote:
> > On Thu, Jun 27, 2013 at 09:34:32AM +0300, Timo Teräs wrote:
> > > 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()).
> >
> > Wouldn't it be more logical to prevent this from happening by not
> > using a refcount of zero? For example, NODELETE could just perform
> > an extra increment on the refcnt so that it never reaches 0. In
> > essence, the NODELETE flag is a permanent reference to the DSO.
> I was thinking the same, without having looked yet. This does not
> sound like the correct fix.

This would be the alternate patch - but somehow I lost my original test
case. And qemu seems to now depend on GTK making the other known issue
also go away.

Paolo, could you test if this fixes your problem also?

diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index 96459f3..71133dd 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -831,6 +831,8 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags,
 #endif
        (*rpnt)->dyn = tpnt;
        tpnt->usage_count++;
+       if (rtld_flags & RTLD_NODELETE)
+               tpnt->usage_count++;
 #ifdef __LDSO_STANDALONE_SUPPORT__
        tpnt->libtype = (epnt->e_type == ET_DYN) ? elf_lib : elf_executable;
 #else
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index c451b63..035b56d 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -822,7 +822,7 @@ static int do_dlclose(void *vhandle, int need_fini)
                _dl_handles = rpnt->next_handle;
        _dl_if_debug_print("%s: usage count: %d\n",
                        handle->dyn->libname, handle->dyn->usage_count);
- if (handle->dyn->usage_count != 1 || (handle->dyn->rtld_flags & RTLD_NODELETE)) {
+       if (handle->dyn->usage_count != 1) {
                handle->dyn->usage_count--;
                free(handle);
                return 0;
@@ -844,7 +844,7 @@ static int do_dlclose(void *vhandle, int need_fini)
        for (j = 0; j < handle->init_fini.nlist; ++j) {
                tpnt = handle->init_fini.init_fini[j];
                tpnt->usage_count--;

We want to keep usage_count at at least 1 if NODELETE here in dlclose:
tpnt->usage_count -= !(tpnt->rtld_flags & RTLD_NODELETE);
Instead, or, better -- and then
usage_count = MAX(usage_count, usage_count & RTLD_NODELETE);
or something to that effect.

Thanks,
-               if (tpnt->usage_count == 0 && !(tpnt->rtld_flags & 
RTLD_NODELETE)) {
+               if (tpnt->usage_count == 0) {
                        if ((tpnt->dynamic_info[DT_FINI]
                             || tpnt->dynamic_info[DT_FINI_ARRAY])
                         && need_fini


Sent with AquaMail for Android
http://www.aqua-mail.com


_______________________________________________
uClibc mailing list
uClibc@uclibc.org
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to