Repository navigation
Conversation
|
casaroli
force-pushed
the
libelf-per-task-registry
branch
from
October 7, 2026 19:26
69e3fe6 to
52e93c8
Compare
Contributor
Author
|
@xiaoxiang781216 i think this is breaking change. Should I mark it and bring a vote to the list? |
Contributor
the old behavior doesn't compliant to POSIX, this patch fix the problem. So, I think it's a bug fix.:) |
One global registry held every ELF object that dlopen(), insmod() and the DT_NEEDED loader loaded. Thus a library was one instance for the whole system, and all task groups shared its data. Put the objects that dlopen() loads on a registry in struct task_info_s, so each task group records the libraries it loaded. POSIX makes a dlopen() handle valid in the whole process, so the registry is per task group and not per thread. Kernel modules of insmod() stay on the global registry, and /proc/modules shows only them. A DT_NEEDED library goes on the registry of the module that needs it. A program that exec() loads collects its libraries on its own registry. In a flat build, exec_module() moves them to the registry of the new task group, so dlopen() in the program finds the same copy. In the protected build the program is loaded by the kernel libc, which has another lock and heap, so its libraries stay on its own registry. Close the libraries that a task group did not close when it exits. In a flat build, group_release() does it after the last thread, before it unloads the program. In the protected build the kernel cannot reach the user registry, so exit() does it. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Describe the per task group registry: each task group loads its own copy of a library, constructors and destructors run once per task group, and a task group closes what it left open when it exits. Kernel modules stay on one list for the system. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
casaroli
force-pushed
the
libelf-per-task-registry
branch
from
October 8, 2026 06:24
52e93c8 to
a04d4c0
Compare
casaroli
marked this pull request as ready for review
October 8, 2026 06:50
casaroli
requested review from
Donny9,
GUIDINGLI,
anchao,
jerpelea,
masayuki2009,
pussuw,
xiaoxiang781216 and
yamt
as code owners
October 8, 2026 06:50
Contributor
Author
|
ok, i agree |
acassis
approved these changes
Oct 8, 2026
❌ Cross-repo dependency could not be appliedThe Build report says the declared dependency PR(s) could not be applied, so CI did not run against the combined code: Reason: cherry-pick failed (if your PR has merge commits, rebase instead) CI run: https://github.com/apache/nuttx/actions/runs/38088049757 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Each task group now has its own registry of the ELF objects that
dlopen()loads, as suggested in #20132. The registry is instruct task_info_sand not instruct tls_info_s, because POSIX makes adlopen()handle valid in the whole process, not only in the thread that opened it.Kernel modules from
insmod()stay on one registry for the system, and/proc/modulesshows only them.A library that a module names in
DT_NEEDEDgoes on the registry of that module. In a flat build,exec()gives the libraries of the program to the new task group, sodlopen()in the program finds the same copy.When a task group exits, the libraries that it did not close are closed. A flat build does this in
group_release(), after the last thread. A protected build does it inexit(), because the kernel cannot reach the user registry.Impact
Two processes that use one library now each have their own copy of its data, and its constructors and destructors run once per process. An FDPIC library executed in place from xipfs still shares its text.
A library that is not executed in place is now loaded once per process, so its text uses RAM in each process.
A program loaded by
exec()no longer resolves symbols from libraries that other processes loaded, or frominsmod()modules.dlopen()handles that a process does not close are now freed when it exits. Before, they stayed loaded.The xipfs C++ test in apps checks the old shared behaviour. apache/nuttx-apps#3813 changes it.
Testing
Arm GNU Toolchain 13.2.rel1, QEMU
mps2-an500.xipfs_test fdpic(FDPIC,mps2-an500:xipfs)fdpicxip solibfdpicxip cxxsotest(plain ELF)sotestthat exits with its libraries openmps2-an500:knsh(protected) with ELF and dlfcn:ostestqemu-armv7a:knsh(kernel) with dlfcnesp32s3-devkit:kernel_n8r2(kernel,CONFIG_LIBC_ELF), kernel and user programsesp32s3-devkit:kernel_oct(kernel,CONFIG_LIBC_ELF) on an ESP32-S3-WROOM-2-N32R8V:ostestandsandboxostestexits 0,fork()passes;sandboxreports every check passedtools/checkpatch.sh -c -u -m -gpasses.