Re: PR lib/59751: dlclose is not MT-safe depending on the libraries unloaded
Taylor R Campbell <[email protected]>
| Newsgroups | gmane.os.netbsd.bugs |
|---|---|
| Message-ID | <[email protected]> |
> Date: Wed, 15 Jul 2026 23:54:56 +0200 > From: Anthony Mallet <[email protected]> > > I was actually trying to debug dlclose(3) issues in a complex C++ > program (not related to this PR at all). Then I found this report and > the associated recent commits, so I gave it a try as it looked > promising for my case too. > > Now, (with -current and ld.elf_so from today) it seems that > _recursive_ dlclose() calls blocks infinitely. I can try to provide > a minimal reproducer, but I wanted to let you know first, in case you can > quickly spot or figure out the issue. Darnit! That's probably much worse than requiring the caller to serialize dlopen/dlclose, which was an effective workaround for the original problem this PR was about... > Note that the recursive dlclose, as weird as it looks, is expected to > happen given the way the code is written. The two dlclose are not > targetting the same libraries, although both libraries have many > dependencies in common. I'm not sure if recursive dlclose is not > undefined behaviour though. I don't know if it's really defined by a standard but it's a reasonable thing to do. Can you try the attached patch and see if it works in your complex application? I haven't really thought through the implications but it makes a simple test pass.
pr59751-recursivedlopendlclose.patch
(text/plain, 2.6 KB)
# HG changeset patch # User Taylor R Campbell <[email protected]> # Date 1784160130 0 # Thu Jul 16 00:02:10 2026 +0000 # Branch trunk # Node ID cd0994f0feb0884c98f4ab9523142cd99fabde47 # Parent 05f0f4cd0342e5f669a0e3bfdb589842a248e4a4 # EXP-Topic riastradh-pr59751-recursivedlopendlclose WIP: dlfcn(3): Allow recursive dlopen/dclose again through init/fini. PR lib/59751: dlclose is not MT-safe depending on the libraries unloaded diff -r 05f0f4cd0342 -r cd0994f0feb0 libexec/ld.elf_so/rtld.c --- a/libexec/ld.elf_so/rtld.c Wed Jul 15 23:56:27 2026 +0000 +++ b/libexec/ld.elf_so/rtld.c Thu Jul 16 00:02:10 2026 +0000 @@ -529,6 +529,8 @@ restart: if (obj->refcount > 0 && !force) { continue; } + if (obj->initfinilock == _lwp_self()) + continue; if (!_rtld_initfini_enter(&obj, mask)) { _rtld_objlist_clear(&finilist); goto restart; @@ -549,6 +551,8 @@ restart: if (obj->refcount > 0 && !force) { continue; } + if (obj->initfinilock == _lwp_self()) + continue; if (!_rtld_initfini_enter(&obj, mask)) { _rtld_objlist_clear(&finilist); goto restart; @@ -600,6 +604,8 @@ static void static bool _rtld_call_ifunc_functions(sigset_t *mask, Obj_Entry *obj, u_int cur_objgen) { + if (obj->initfinilock == _lwp_self()) + return false; if (!_rtld_initfini_enter(&obj, mask)) return true; if (obj->ifunc_remaining @@ -683,6 +689,8 @@ restart: goto restart; } if (obj->z_initfirst) { + if (obj->initfinilock == _lwp_self()) + continue; if (!_rtld_initfini_enter(&obj, mask)) { _rtld_objlist_clear(&initlist); goto restart; @@ -704,6 +712,8 @@ restart: _rtld_objlist_clear(&initlist); goto restart; } + if (obj->initfinilock == _lwp_self()) + continue; if (!_rtld_initfini_enter(&obj, mask)) { _rtld_objlist_clear(&initlist); goto restart; diff -r 05f0f4cd0342 -r cd0994f0feb0 tests/libexec/ld.elf_so/t_dlclose_thread.c --- a/tests/libexec/ld.elf_so/t_dlclose_thread.c Wed Jul 15 23:56:27 2026 +0000 +++ b/tests/libexec/ld.elf_so/t_dlclose_thread.c Thu Jul 16 00:02:10 2026 +0000 @@ -116,13 +116,6 @@ ATF_TC_BODY(dlclose_recursive, tc) RL(timer_create(CLOCK_MONOTONIC, &sigev, &t)); RL(timer_settime(t, TIMER_RELTIME, &it, NULL)); - /* - * Really, the issue is the followup to the fix for the PR - * which is that I broke recursive dlopen/dlclose! - */ - atf_tc_expect_signal(SIGABRT, "PR lib/59751: dlclose is not MT-safe" - " depending on the libraries unloaded"); - handle = dlopen("libh_helper_recurdso.so", RTLD_LAZY | RTLD_LOCAL); ATF_REQUIRE_MSG(handle != NULL, "%s", dlerror()); ATF_REQUIRE_MSG((error = dlclose(handle)) == 0,