PR/59751 CVS commit: [netbsd-11] src
"Martin Husemann" <[email protected]> Sun, 19 Jul 2026 16:20:01 +0000 (UTC)
| Newsgroups | gmane.os.netbsd.bugs |
|---|---|
| Message-ID | <[email protected]> |
The following reply was made to PR lib/59751; it has been noted by GNATS. From: "Martin Husemann" <[email protected]> To: [email protected] Cc: Subject: PR/59751 CVS commit: [netbsd-11] src Date: Sun, 19 Jul 2026 16:17:14 +0000 Module Name: src Committed By: martin Date: Sun Jul 19 16:17:14 UTC 2026 Modified Files: src/distrib/sets/lists/debug [netbsd-11]: shl.mi src/distrib/sets/lists/tests [netbsd-11]: shl.mi src/libexec/ld.elf_so [netbsd-11]: reloc.c rtld.c rtld.h xmalloc.c src/tests/libexec/ld.elf_so [netbsd-11]: Makefile t_dlclose_thread.c Added Files: src/tests/libexec/ld.elf_so/helper_recurdso [netbsd-11]: Makefile h_helper_recurdso.c src/tests/libexec/ld.elf_so/helper_recurdso2 [netbsd-11]: Makefile h_helper_recurdso2.c Log Message: Pull up following revision(s) (requested by riastradh in ticket #386): tests/libexec/ld.elf_so/helper_recurdso2/Makefile: revision 1.1 distrib/sets/lists/tests/shl.mi: revision 1.18 tests/libexec/ld.elf_so/t_dlclose_thread.c: revision 1.4 tests/libexec/ld.elf_so/t_dlclose_thread.c: revision 1.5 tests/libexec/ld.elf_so/t_dlclose_thread.c: revision 1.6 libexec/ld.elf_so/rtld.c: revision 1.227 libexec/ld.elf_so/xmalloc.c: revision 1.26 tests/libexec/ld.elf_so/helper_recurdso/Makefile: revision 1.1 tests/libexec/ld.elf_so/Makefile: revision 1.36 libexec/ld.elf_so/rtld.h: revision 1.157 tests/libexec/ld.elf_so/helper_recurdso/h_helper_recurdso.c: revision 1.1 tests/libexec/ld.elf_so/helper_recurdso2/h_helper_recurdso2.c: revision 1.1 distrib/sets/lists/debug/shl.mi: revision 1.410 libexec/ld.elf_so/reloc.c: revision 1.122 t_dlclose_thread: Test recursive dlopen/dlclose too. Simple test first: - h_helper_recurdso dlopens h_helper_dso2 - h_helper_dso2 needs h_helper_dso1 When dlopening h_helper_recurdso, the initialization order must be: ENTER h_helper_recurdso -> h_helper_dso1 -> h_helper_dso2 LEAVE h_helper_recurdso For the more complex test, we have the relations: - h_helper_recurdso2 needs h_helper_recurdso - h_helper_recurdso dlopens h_helper_dso2 - h_helper_dso2 needs h_helper_dso1 (And the finalization order must be in reverse.) When dlopening h_helper_recurdso2, the initialization order, therefore, must be: ENTER h_helper_recurdso -> h_helper_dso1 -> h_helper_dso2 LEAVE h_helper_recurdso h_helper_recurdso2 PR lib/59751: dlclose is not MT-safe depending on the libraries unloaded (Really, this is about a followup bug in the fix for that issue, which broke recursive dlopen/dlclose.) t_dlclose_thread: Make timeouts manifest more predictably. And use SIGABRT to get stack traces. PR lib/59751: dlclose is not MT-safe depending on the libraries unloaded ld.elf_so: Fix more races with recursive threaded dlopen/dlclose. 1. When loading an object, keep track of a finer-grained state for relocation so that a concurrent _rtld_relocate_objects doesn't relocate an object too early (e.g., while waiting in _rtld_load_needed_objects for an object that is concurrently being dlclosed to finish before we can map it afresh) leading to spurious symbol resolution failures: - OBJRELOC_NONE (0): object has been created but the rtld state isn't enough to attempt relocation yet (either not all DT_NEEDED entries have been resolved, or the dldags lists have not yet been populated) - OBJRELOC_READY (1): object has been created and rtld state is ready to relocate (all DT_NEEDED entries have been resolved and the dldags lists have been populated), but object has not yet been relocated. - OBJRELOC_DONE (2): object has been relocated successfully. - OBJRELOC_FAILED (3): relocation failed, e.g. because of symbol resolution failure. Allowed transitions: - NONE->READY - READY->DONE - READY->FAILED 2. When calling dlopen/dlclose from an object's constructor or destructor, exclude that object and any object that needs it from the topological ordering of objects for constructor/destructor calls inside dlopen/dlclose -- we can't re-enter the same object's constructor or destructor, and before the object's constructor or destructor has returned (which can't happen until the recursive dlopen or dlclose has returned), it would be wrong to invoke the constructor or destructor of any object that needs it. 3. When dlclosing an object, mark any of its dagmembers as busy dlclosing so a concurrent GC loop at the end of _rtld_unload_object doesn't free them while we sleep in init/fini functions before we can remove the DAG from the members' dldags. Later, at the end of this call to _rtld_unload_object, we will take care of them. This requires changing the boolean dlclosing state to an integer reference count. `int' is big enough because each thread can hold at most one reference to each object, so the number of threads is an upper bound on the reference count. Unfortunately, there is still a bug lurking: every now and then, t_dlclose_thread:dlclose_thread_recursive2 trips one of the abort branches in libh_helper_recurdso2.so, e.g. because the destructor for libh_helper_recurdso.so ran first. But the frequency of these failures has gone down dramatically, from around 19/20 to about 1/20 trials. Simply serializing dlopen/dlclose calls in an application is likely to be an effective workaround. And these changes fix issues in single-threaded recursive dlopen/dlclose even if the multithreaded case has a remaining low-probability race. PR lib/59751: dlclose is not MT-safe depending on the libraries unloaded ld.elf_so: Fix ASSERT macro in xmalloc.c. 1. Use #p, not "p", in the expansion of #define ASSERT(p), for C as of this millennium. 2. Consistently make ASSERT(...) a single expression. Prompted by enabling MALLOC_DEBUG to track down issues in: PR lib/59751: dlclose is not MT-safe depending on the libraries unloaded To generate a diff of this commit: cvs rdiff -u -r1.367.2.11 -r1.367.2.12 src/distrib/sets/lists/debug/shl.mi cvs rdiff -u -r1.16.4.1 -r1.16.4.2 src/distrib/sets/lists/tests/shl.mi cvs rdiff -u -r1.120.2.1 -r1.120.2.2 src/libexec/ld.elf_so/reloc.c cvs rdiff -u -r1.221.2.3 -r1.221.2.4 src/libexec/ld.elf_so/rtld.c cvs rdiff -u -r1.150.2.3 -r1.150.2.4 src/libexec/ld.elf_so/rtld.h cvs rdiff -u -r1.12.44.1 -r1.12.44.2 src/libexec/ld.elf_so/xmalloc.c cvs rdiff -u -r1.28.2.3 -r1.28.2.4 src/tests/libexec/ld.elf_so/Makefile cvs rdiff -u -r1.1.2.3 -r1.1.2.4 \ src/tests/libexec/ld.elf_so/t_dlclose_thread.c cvs rdiff -u -r0 -r1.1.2.2 \ src/tests/libexec/ld.elf_so/helper_recurdso/Makefile \ src/tests/libexec/ld.elf_so/helper_recurdso/h_helper_recurdso.c cvs rdiff -u -r0 -r1.1.2.2 \ src/tests/libexec/ld.elf_so/helper_recurdso2/Makefile \ src/tests/libexec/ld.elf_so/helper_recurdso2/h_helper_recurdso2.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.