NetBSD Problem Report #59751
From www@netbsd.org Sat Nov 8 19:51:35 2025
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits)
client-signature RSA-PSS (2048 bits))
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id 1E0221A923C
for <gnats-bugs@gnats.NetBSD.org>; Sat, 8 Nov 2025 19:51:35 +0000 (UTC)
Message-Id: <20251108195133.B9D321A923E@mollari.NetBSD.org>
Date: Sat, 8 Nov 2025 19:51:33 +0000 (UTC)
From: netbsd@kazlauskas.me
Reply-To: netbsd@kazlauskas.me
To: gnats-bugs@NetBSD.org
Subject: dlclose is not MT-safe depending on the libraries unloaded
X-Send-Pr-Version: www-1.0
>Number: 59751
>Category: lib
>Synopsis: dlclose is not MT-safe depending on the libraries unloaded
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: riastradh
>State: analyzed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Nov 08 19:55:00 +0000 2025
>Closed-Date:
>Last-Modified: Thu Dec 18 18:05:01 +0000 2025
>Originator: Simonas K.
>Release: 10.1
>Organization:
N/A
>Environment:
NetBSD 10.1 NetBSD 10.1 (GENERIC) #0: Mon Dec 16 13:08:11 UTC 2024 mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/amd64/compile/GENERIC amd64
>Description:
It looks like unloading dynamically loaded libraries via `dlclose` can result in applications SIGSEGV'ing with all sorts of stack traces such as:
```
* thread #1, stop reason = signal SIGSEGV
* frame #0: 0x000075c01b8419e0
frame #1: 0x00007f7eaa205e04 ld.elf_so`_rtld_call_fini_function + 135
frame #2: 0x00007f7eaa2061bd ld.elf_so`_rtld_unload_object.part.0 + 700
frame #3: 0x00007f7eaa2074b2 ld.elf_so`dlclose + 233
...
```
```
* frame #0: 0x00007f7f03a07fab ld.elf_so`_rtld_symlook_obj + 619
frame #1: 0x00007f7f03a083ea ld.elf_so`_rtld_symlook_list + 185
frame #2: 0x00007f7f03a0889f ld.elf_so`_rtld_symlook_default + 530
frame #3: 0x00007f7f03a08d4a ld.elf_so`_rtld_find_plt_symdef + 221
frame #4: 0x00007f7f03a00bc0 ld.elf_so`_rtld_bind + 75
frame #5: 0x00007f7f03a0082d ld.elf_so`_rtld_bind_start + 29
...
```
```
* frame #0: 0x000073c4aaa10e6f libgcc_s.so.1`__deregister_frame_info_bases + 70
frame #1: 0x000073c4aa446705 libc.so.12`__do_global_dtors_aux + 85
frame #2: 0x000073c4aa584919 libc.so.12`_fini + 9
frame #3: 0x00007f7e90805e04 ld.elf_so`_rtld_call_fini_function + 135
frame #4: 0x00007f7e9080623d ld.elf_so`_rtld_unload_object.part.0 + 828
frame #5: 0x00007f7e908074b2 ld.elf_so`dlclose + 233
...
```
etc. Not unloading the libraries (i.e. commenting out `dlclose`) makes the SIGSEGVs go away. It seems like this may be related to the fact that the library loaded/unloaded has dtors. In my case the code being tested is a Rust library over dl* primitives (rust_libloading) and the dynamic library used is not especially interesting (e.g. it has just a few pure functions and don't do risky stuff as spawning threads.)
>How-To-Repeat:
* git clone https://github.com/nagisa/rust_libloading
* cargo test
* observe sigsegv (make sure to run on a multi-core system.)
You can comment out the two occurrences of `dlclose` in `src/os/unix/mod.rs` to check that it is indeed `dlclose` that's having a poor interaction with *something*. You can also comment out the code involving `dlerror` to rule out any potential MT-unsafety related issues.
The code for library being loaded and unloaded is available at `src/test_helpers.rs` which can be independently compiled with `rustc src/test_helpers.rs -o test_helpers.so`.
>Fix:
A number of other system library/linker/loader implementations transparently refuse to unload libraries that e.g. register thread locals. An example of this is MacOS. I'm semi-confident that nothing of the sort is happening in `rust_libloading`s tests though and the shared object is extremely straighforward, so something deeper is going on here.
---
P.S. it would be nice if `dlerror` was made MT-safe (by e.g. maintaining a thread-local error buffer.)
P.P.S. I'm just forwarding a bug report made against rust_libloading after some initial investigation. I'm happy to help with brainstorming possible causes.
>Release-Note:
>Audit-Trail:
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/59751 CVS commit: src
Date: Sun, 23 Nov 2025 22:01:14 +0000
Module Name: src
Committed By: riastradh
Date: Sun Nov 23 22:01:14 UTC 2025
Modified Files:
src/distrib/sets/lists/debug: mi
src/distrib/sets/lists/tests: mi
src/tests/libexec/ld.elf_so: Makefile
Added Files:
src/tests/libexec/ld.elf_so: t_dlclose_thread.c
Log Message:
ld.elf_so(1): Test concurrent dlopen/dlclose.
PR lib/59751: dlclose is not MT-safe depending on the libraries
unloaded
To generate a diff of this commit:
cvs rdiff -u -r1.490 -r1.491 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.1400 -r1.1401 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.28 -r1.29 src/tests/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/libexec/ld.elf_so/t_dlclose_thread.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Responsible-Changed-From-To: lib-bug-people->riastradh
Responsible-Changed-By: riastradh@NetBSD.org
Responsible-Changed-When: Sun, 23 Nov 2025 22:30:02 +0000
Responsible-Changed-Why:
mine
State-Changed-From-To: open->analyzed
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Sun, 23 Nov 2025 22:30:02 +0000
State-Changed-Why:
The main culprit is that while dlopen and dlclose are mostly serialized
by the rtld exclusive lock, they drop that lock to call constructors
and destructors -- and when that happens, they can get interleaved and
observe troublesome intermediate states.
I added a test case for this, and drafted a patch to address this by
serializing the constructor and destructor calls and deferring
unmapping/freeing objects until any concurrent dlclose activity on them
has completed -- could stand some more review and testing before I
commit:
https://mollari.NetBSD.org/~riastradh/tmp/20251122/pr59751-dlcloserace-v2.patch
https://mollari.NetBSD.org/~riastradh/tmp/20251122/pr59751-dlcloserace-v2.diff
From: "Martin Husemann" <martin@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/59751 CVS commit: [netbsd-11] src
Date: Thu, 18 Dec 2025 18:03:34 +0000
Module Name: src
Committed By: martin
Date: Thu Dec 18 18:03:33 UTC 2025
Modified Files:
src/distrib/sets/lists/debug [netbsd-11]: mi
src/distrib/sets/lists/tests [netbsd-11]: mi
src/tests/libexec/ld.elf_so [netbsd-11]: Makefile
Added Files:
src/tests/libexec/ld.elf_so [netbsd-11]: t_dlclose_thread.c
Log Message:
Pull up following revision(s) (requested by riastradh in ticket #127):
distrib/sets/lists/tests/mi: revision 1.1401
tests/libexec/ld.elf_so/t_dlclose_thread.c: revision 1.1
distrib/sets/lists/debug/mi: sort + revision 1.491
tests/libexec/ld.elf_so/Makefile: revision 1.29
ld.elf_so(1): Test concurrent dlopen/dlclose.
PR lib/59751: dlclose is not MT-safe depending on the libraries
unloaded
To generate a diff of this commit:
cvs rdiff -u -r1.485.2.3 -r1.485.2.4 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.1387.2.2 -r1.1387.2.3 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.28 -r1.28.2.1 src/tests/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.1.2.2 src/tests/libexec/ld.elf_so/t_dlclose_thread.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2025
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.