[libc][libdl] Fix dlopen() failing to find already-loaded modules

Fix name mismatch between dlmodule_find() and _dlmodule_set_name() that
caused dlopen() to always reload modules instead of reusing them:

1. In dlopen(): Extract module name from full path before calling
   dlmodule_find(), matching the stripped name stored by _dlmodule_set_name().
   This allows dlopen() to properly find and reuse already-loaded modules.

2. In _dlmodule_set_name(): Fix bug where extension detection searched
   the entire path instead of just the filename portion. For paths like
   "/mnt/v1.2/app.so", it would incorrectly find "." in "v1.2" directory
   name instead of the ".so" extension.

Fixes: Module reloading on every dlopen() call, memory leaks from
duplicate module instances, and dlclose() cleanup issues.

Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-19 02:34:34 +00:00
parent ec3b2a2d76
commit 8a99de1747
2 changed files with 65 additions and 12 deletions

View File

@@ -44,17 +44,29 @@ static void _dlmodule_set_name(struct rt_dlmodule *module, const char *path)
ptr = first = (char *)path;
end = path + rt_strlen(path);
/* find the start of filename (after last '/') */
while (*ptr != '\0')
{
if (*ptr == '/')
first = ptr + 1;
if (*ptr == '.')
end = ptr - 1;
ptr ++;
ptr++;
}
size = end - first + 1;
/* find extension in filename portion only (after last '/') */
ptr = first;
while (*ptr != '\0')
{
if (*ptr == '.')
end = ptr;
ptr++;
}
size = end - first;
if (size <= 0)
{
/* no extension found, use entire filename */
size = rt_strlen(first);
}
if (size >= RT_NAME_MAX) size = RT_NAME_MAX - 1;
rt_strncpy(object->name, first, size);

View File

@@ -33,7 +33,8 @@ void* dlopen(const char *filename, int flags)
{
struct rt_dlmodule *module;
char *fullpath;
const char*def_path = MODULE_ROOT_DIR;
const char *def_path = MODULE_ROOT_DIR;
char module_name[RT_NAME_MAX];
/* check parameters */
RT_ASSERT(filename != RT_NULL);
@@ -48,15 +49,55 @@ void* dlopen(const char *filename, int flags)
}
else
{
fullpath = (char*)filename; /* absolute path, use it directly */
fullpath = (char *)filename; /* absolute path, use it directly */
}
/* Extract module name from path (strip directory and extension)
* This matches the logic in _dlmodule_set_name() so that dlmodule_find()
* can properly locate already-loaded modules by their stored name.
*/
{
const char *first, *end, *ptr;
int size;
ptr = first = fullpath;
end = fullpath + strlen(fullpath);
while (*ptr != '\0')
{
if (*ptr == '/')
first = ptr + 1;
ptr++;
}
/* find extension in filename portion only (after last '/') */
ptr = first;
while (*ptr != '\0')
{
if (*ptr == '.')
end = ptr;
ptr++;
}
size = end - first;
if (size <= 0)
{
/* no extension found, use entire filename */
size = strlen(first);
}
if (size >= RT_NAME_MAX)
size = RT_NAME_MAX - 1;
rt_strncpy(module_name, first, size);
module_name[size] = '\0';
}
rt_enter_critical();
/* find in module list */
module = dlmodule_find(fullpath);
/* find in module list using the stripped module name */
module = dlmodule_find(module_name);
if(module != RT_NULL)
if (module != RT_NULL)
{
rt_exit_critical();
module->nref++;
@@ -67,11 +108,11 @@ void* dlopen(const char *filename, int flags)
module = dlmodule_load(fullpath);
}
if(fullpath != filename)
if (fullpath != filename)
{
rt_free(fullpath);
}
return (void*)module;
return (void *)module;
}
RTM_EXPORT(dlopen);