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); >