On Sun, 25 Oct 2015 11:01:27 +0100,
Peter Hajdu wrote:
> 
> [1  <text/plain; us-ascii (7bit)>]
> Hi,
> 
> I try to give it one more attempt with a bit more description about the
> bug.
> 
> After calling dlclose in _dl_notify_unload_shlib_ group reference counts
> are decreased by following the object's grpref-list.  Unfortunately the
> references are removed from the list during the graph traversal.
> 
> dlclose will run all destructors of the unused objects and tries to
> unload all objects reachable from the closed object's child and
> grpref-list.  Since the grpref-list references were removed, the unused
> destructed object stays in memory as garbage.  Next time when this
> object is loaded it is found in the memory and crashes during load.
> 
> This patch unloads all unused objects instead of following the closed
> object's child and grpref list.
> 
> Best regards,
> Peter Hajdu
> 

Hello,

I can confirm that this works with sdl2 on a maybe 4 week old snapshot
on amd64.
I used that old patch that was flying around to get sdl2 up and
running, now I replaced ld.so with a fresh checkout, applied the
patch and sdl2 still works fine, no other problems observed.

Thanks a lot,

Alf

> [2 ldso_fix.diff <text/plain; us-ascii (7bit)>]
> Index: dlfcn.c
> ===================================================================
> RCS file: /cvs/src/libexec/ld.so/dlfcn.c,v
> retrieving revision 1.91
> diff -u -p -r1.91 dlfcn.c
> --- dlfcn.c   19 Sep 2015 20:56:47 -0000      1.91
> +++ dlfcn.c   21 Oct 2015 13:52:46 -0000
> @@ -302,7 +302,7 @@ _dl_real_close(void *handle)
>       object->opencount--;
>       _dl_notify_unload_shlib(object);
>       _dl_run_all_dtors();
> -     _dl_unload_shlib(object);
> +     _dl_unload_unused();
>       _dl_cleanup_objects();
>       return (0);
>  }
> Index: library.c
> ===================================================================
> RCS file: /cvs/src/libexec/ld.so/library.c,v
> retrieving revision 1.71
> diff -u -p -r1.71 library.c
> --- library.c 16 Jan 2015 16:18:07 -0000      1.71
> +++ library.c 21 Oct 2015 13:52:46 -0000
> @@ -74,6 +74,22 @@ _dl_unload_shlib(elf_object_t *object)
>       }
>  }
>  
> +void
> +_dl_unload_unused(void)
> +{
> +     elf_object_t *obj, *next;
> +
> +     for (obj = _dl_objects->next; obj != NULL; obj = next) {
> +             next = obj->next;
> +             if (OBJECT_REF_CNT(obj) != 0 || obj->status & STAT_UNLOADED)
> +                     continue;
> +             obj->status |= STAT_UNLOADED;
> +             _dl_load_list_free(obj->load_list);
> +             _dl_munmap((void *)obj->load_base, obj->load_size);
> +             _dl_remove_object(obj);
> +     }
> +}
> +
>  elf_object_t *
>  _dl_tryload_shlib(const char *libname, int type, int flags)
>  {
> Index: library_mquery.c
> ===================================================================
> RCS file: /cvs/src/libexec/ld.so/library_mquery.c,v
> retrieving revision 1.49
> diff -u -p -r1.49 library_mquery.c
> --- library_mquery.c  22 Jan 2015 05:48:17 -0000      1.49
> +++ library_mquery.c  21 Oct 2015 13:52:46 -0000
> @@ -79,6 +79,20 @@ _dl_unload_shlib(elf_object_t *object)
>       }
>  }
>  
> +void
> +_dl_unload_unused(void)
> +{
> +     elf_object_t *obj, *next;
> +
> +     for (obj = _dl_objects->next; obj != NULL; obj = next) {
> +             next = obj->next;
> +             if (OBJECT_REF_CNT(obj) != 0 || obj->status & STAT_UNLOADED)
> +                     continue;
> +             obj->status |= STAT_UNLOADED;
> +             _dl_load_list_free(obj->load_list);
> +             _dl_remove_object(obj);
> +     }
> +}
>  
>  elf_object_t *
>  _dl_tryload_shlib(const char *libname, int type, int flags)
> Index: resolve.h
> ===================================================================
> RCS file: /cvs/src/libexec/ld.so/resolve.h,v
> retrieving revision 1.73
> diff -u -p -r1.73 resolve.h
> --- resolve.h 19 Sep 2015 20:56:47 -0000      1.73
> +++ resolve.h 21 Oct 2015 13:52:46 -0000
> @@ -223,6 +223,7 @@ void _dl_unlink_dlopen(elf_object_t *dep
>  void _dl_notify_unload_shlib(elf_object_t *object);
>  void _dl_unload_shlib(elf_object_t *object);
>  void _dl_unload_dlopen(void);
> +void _dl_unload_unused(void);
>  
>  void _dl_run_all_dtors(void);
>  

Reply via email to