NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

PR/59751 CVS commit: src



The following reply was made to PR lib/59751; it has been noted by GNATS.

From: "Taylor R Campbell" <riastradh%netbsd.org@localhost>
To: gnats-bugs%gnats.NetBSD.org@localhost
Cc: 
Subject: PR/59751 CVS commit: src
Date: Sat, 18 Jul 2026 04:26:42 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Sat Jul 18 04:26:42 UTC 2026
 
 Modified Files:
 	src/libexec/ld.elf_so: reloc.c rtld.c rtld.h
 	src/tests/libexec/ld.elf_so: t_dlclose_thread.c
 
 Log Message:
 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
 
 
 To generate a diff of this commit:
 cvs rdiff -u -r1.121 -r1.122 src/libexec/ld.elf_so/reloc.c
 cvs rdiff -u -r1.226 -r1.227 src/libexec/ld.elf_so/rtld.c
 cvs rdiff -u -r1.156 -r1.157 src/libexec/ld.elf_so/rtld.h
 cvs rdiff -u -r1.5 -r1.6 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.
 



Home | Main Index | Thread Index | Old Index