From f7a628267af575bdbfe478c11ceef875087252b8 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Mon, 3 Aug 2026 12:26:13 +0200 Subject: [PATCH] examples/sotest: Check that a library can be opened twice. dlopen() of an already loaded library used to fail, so nothing exercised what happens when two callers hold the same object. Open the library a second time, check the same handle comes back, close one of the two and check the library is still usable through the other. Needs the counterpart change in nuttx; without it the second dlopen() returns NULL and this reports it. Assisted-by: Claude Opus 5 (1M context) Signed-off-by: Marco Casaroli --- examples/sotest/main/sotest_main.c | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/examples/sotest/main/sotest_main.c b/examples/sotest/main/sotest_main.c index 6b2417ddb21..94b7eab8180 100644 --- a/examples/sotest/main/sotest_main.c +++ b/examples/sotest/main/sotest_main.c @@ -130,6 +130,7 @@ int main(int argc, FAR char *argv[]) FAR void *handle1; #endif FAR void *handle2; + FAR void *handle3; CODE void (*testfunc)(FAR const char *msg); FAR const char *msg; int ret; @@ -326,6 +327,42 @@ int main(int argc, FAR char *argv[]) testfunc(msg); + /* Open the same library again. dlopen() must return the object that is + * already loaded, and closing one of the two handles must leave the + * other usable. + */ + + handle3 = dlopen(sotest_path, RTLD_NOW | RTLD_LOCAL); + if (handle3 == NULL) + { + fprintf(stderr, "ERROR: dlopen(%s) failed on an already loaded " + "library\n", sotest_path); + exit(EXIT_FAILURE); + } + + if (handle3 != handle2) + { + fprintf(stderr, "ERROR: dlopen() returned %p for a library already " + "loaded at %p\n", handle3, handle2); + exit(EXIT_FAILURE); + } + + ret = dlclose(handle3); + if (ret != 0) + { + fprintf(stderr, "ERROR: dlclose(handle3) failed: %d\n", ret); + exit(EXIT_FAILURE); + } + + testfunc = (CODE void (*)(FAR const char *))dlsym(handle2, "testfunc1"); + if (testfunc == NULL) + { + fprintf(stderr, "ERROR: closing one handle unloaded the library\n"); + exit(EXIT_FAILURE); + } + + testfunc(msg); + #if CONFIG_LIBC_ELF_MAXDEPEND > 0 /* This should fail because the second shared library depends on * the first.