This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit f2a186ee5f03ce1526bb126681f104277879549c
Author: Marco Casaroli <[email protected]>
AuthorDate: Tue Oct 13 06:56:55 2026 +0200

    libs/libc/elf: Keep the last reference when a close fails.
    
    libelf_remove() set the reference count of a module to zero before
    libelf_uninit() refused to unload it because other modules depend on it.
    The failed dlclose() thus gave up the last reference anyway.  When the
    last dependent went, libelf_undepend() unloaded the module, and the
    next dlclose() of the still open handle failed with ENOENT.
    examples/sotest shows it: "ERROR: dlclose(handle1) failed: -1".
    
    Refuse with EBUSY before the reference is given up, and keep the
    reference if the uninitializer of the module fails.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 libs/libc/elf/elf_remove.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/libs/libc/elf/elf_remove.c b/libs/libc/elf/elf_remove.c
index 82d64746e28..ad00ef99fcb 100644
--- a/libs/libc/elf/elf_remove.c
+++ b/libs/libc/elf/elf_remove.c
@@ -257,12 +257,26 @@ int libelf_remove(FAR void *handle)
       return OK;
     }
 
+#if CONFIG_LIBC_ELF_MAXDEPEND > 0
+  /* The last reference stays while other modules depend on this one: a
+   * failed close must not let the module go later, under the caller.
+   */
+
+  if (modp->dependents > 0)
+    {
+      berr("ERROR: Module has dependents: %d\n", modp->dependents);
+      ret = -EBUSY;
+      goto errout_with_lock;
+    }
+#endif
+
   modp->nopen = 0;
 
   ret = libelf_uninit(modp);
   if (ret < 0)
     {
       berr("ERROR: Failed to uninitialize module %d\n", ret);
+      modp->nopen = 1;
       goto errout_with_lock;
     }
 

Reply via email to