-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Closed
Description
RT-Thread Version
master
Hardware Type/Architectures
all
Develop Toolchain
GCC
Describe the bug
1.如果存在这种情况,线程B持有mutex未释放的情况下,线程A使用rt_thread_detach来分离线程B,线程A是否有必要在关闭线程B后释放其持有的mutex.例如下面的测试代码在目前主线分支中,rt_thread_detach的实现并不会释放被分离线程thread1持有的mutex:
#include <rtthread.h>
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 4096
#define THREAD_TIMESLICE 5
static rt_uint8_t thread1_stack[THREAD_STACK_SIZE];
static struct rt_thread thread1;
/* 定义互斥控制块 */
static rt_mutex_t test_mutex = RT_NULL;
/* 线程1入口函数 */
static void thread1_entry(void *parameter)
{
/* 第一次获取互斥量 */
rt_kprintf("thread1 try to take mutex first time\n");
rt_mutex_take(test_mutex, RT_WAITING_FOREVER);
rt_kprintf("thread1 take mutex first time success\n");
while(1) { rt_thread_mdelay(1000); }
}
int mutex_recursive_test(void)
{
/* 创建递归互斥量 */
test_mutex = rt_mutex_create("test_mutex", RT_IPC_FLAG_PRIO);
if (test_mutex == RT_NULL) {
rt_kprintf("create mutex failed\n");
return -1;
}
/* 初始化静态线程 */
rt_thread_init(&thread1,
"thread1",
thread1_entry,
RT_NULL,
&thread1_stack[0],
sizeof(thread1_stack),
THREAD_PRIORITY,
THREAD_TIMESLICE);
/* 启动线程 */
rt_thread_startup(&thread1);
/* 等待线程运行 */
rt_thread_mdelay(100);
/* 验证主线程无法获取被持有的互斥量 */
rt_kprintf("main thread try to take mutex\n");
if (rt_mutex_take(test_mutex, 1000) == RT_EOK) {
rt_kprintf("[ERROR] main thread take mutex success! This should not happen!\n");
rt_mutex_release(test_mutex);
} else {
rt_kprintf("main thread take mutex timeout, as expected\n");
}
/* 分离静态线程(应自动释放其持有的锁) */
rt_kprintf("main thread detach thread1\n");
rt_thread_detach(&thread1);
/* 验证互斥量是否被正确释放 */
rt_kprintf("main thread try to take mutex after detach\n");
if (rt_mutex_take(test_mutex, 1000) == RT_EOK) {
rt_kprintf("main thread take mutex success after detach\n");
rt_mutex_release(test_mutex);
} else {
rt_kprintf("[BUG] main thread still cannot take mutex! _thread_detach_from_mutex bug triggered!\n");
}
/* 清理资源 */
rt_mutex_delete(test_mutex);
return 0;
}
/* 导出到 msh 命令列表 */
MSH_CMD_EXPORT(mutex_recursive_test, mutex recursive test);
上面的代码中,当前线程在尝试分离thread1后,无法获取thread1持有的锁,这是因为 rt_thread_detach 并未释放thread1持有的mutex,根据调用链:
rt_thread_detach ->_thread_detach -> _thread_detach_from_mutex -> rt_mutex_release
rt_thread_detach 要求调用线程与被分离线程不为同一线程,而rt_mutex_release 要求调用者和mutex持有者为同一线程,这导致实际上执行上面调用链时, rt_mutex_release不会释放被分离线程的mutex
2
不知道按照 rt_thread_detach的设计理念,是否需要释放被分离线程未释放的mutex呢?还是默认被分离线程应该在被分离前自己释放所有mutex,如果没有释放就什么也不做,当异常错误处理?
如果需要释放被分离线程的mutex,这里提供一个解决方案:#10545
Other additional context
No response
Metadata
Metadata
Assignees
Labels
No labels