mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-03-24 17:33:58 +08:00
[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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user