c++ - 取消 pthread_cond_wait() 挂起与 PRIO_INHERIT 互斥锁

标签 c++ c pthreads mutex embedded-linux

2012 年 4 月 10 日更新: Fixed by libc patch


我在 pthread_cond_wait 中取消线程时遇到问题, 将互斥锁与 PTHREAD_PRIO_INHERIT 一起使用属性集。不过,这只发生在某些平台上。

以下最小示例演示了这一点:(使用 g++ <filename>.cpp -lpthread 编译)

#include <pthread.h>
#include <iostream>

pthread_mutex_t mutex;
pthread_cond_t cond;

void clean(void *arg) {
    std::cout << "clean: Unlocking mutex..." << std::endl;
    pthread_mutex_unlock((pthread_mutex_t*)arg);
    std::cout << "clean: Mutex unlocked..." << std::endl;
}

void *threadFunc(void *arg) {
    int ret = 0;
    pthread_mutexattr_t mutexAttr;
    ret = pthread_mutexattr_init(&mutexAttr); std::cout << "ret = " << ret << std::endl;

    //Comment out the following line, and everything works
    ret = pthread_mutexattr_setprotocol(&mutexAttr, PTHREAD_PRIO_INHERIT); std::cout << "ret = " << ret << std::endl;

    ret = pthread_mutex_init(&mutex, &mutexAttr); std::cout << "ret = " << ret << std::endl;
    ret = pthread_cond_init(&cond, 0); std::cout << "ret = " << ret << std::endl;

    std::cout << "threadFunc: Init done, entering wait..." << std::endl;

    pthread_cleanup_push(clean, (void *) &mutex);
    ret = pthread_mutex_lock(&mutex); std::cout << "ret = " << ret << std::endl;
    while(1) {
        ret = pthread_cond_wait(&cond, &mutex); std::cout << "ret = " << ret << std::endl;
    }
    pthread_cleanup_pop(1);

    return 0;
}

int main() {
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, 0, threadFunc, 0); std::cout << "ret = " << ret << std::endl;

    std::cout << "main: Thread created, waiting a bit..." << std::endl;
    sleep(2);

    std::cout << "main: Cancelling threadFunc..." << std::endl;
    ret = pthread_cancel(thread); std::cout << "ret = " << ret << std::endl;

    std::cout << "main: Joining threadFunc..." << std::endl;
    ret = pthread_join(thread, NULL); std::cout << "ret = " << ret << std::endl;

    std::cout << "main: Joined threadFunc, done!" << std::endl;
    return 0;
}

每次我运行它,main()卡在 pthread_join() . gdb 回溯显示如下:

Thread 2 (Thread 0xb7d15b70 (LWP 257)):
#0  0xb7fde430 in __kernel_vsyscall ()
#1  0xb7fcf362 in __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/lowlevellock.S:142
#2  0xb7fcc9f9 in __condvar_w_cleanup () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_wait.S:434
#3  0x08048fbe in threadFunc (arg=0x0) at /home/pthread_cond_wait.cpp:22
#4  0xb7fc8ca0 in start_thread (arg=0xb7d15b70) at pthread_create.c:301
#5  0xb7de73ae in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:130

Thread 1 (Thread 0xb7d166d0 (LWP 254)):
#0  0xb7fde430 in __kernel_vsyscall ()
#1  0xb7fc9d64 in pthread_join (threadid=3083950960, thread_return=0x0) at pthread_join.c:89
#2  0x0804914a in main () at /home/pthread_cond_wait.cpp:41

如果PTHREAD_PRIO_INHERIT未在互斥量上设置,一切正常,程序干净地退出。

有问题的平台:

  • 嵌入式 AMD Fusion 主板,运行 PTXDist基于 32 位 Linux 3.2.9-rt16(带有 RTpatch 16)。我们正在使用最新的 OSELAS i686 交叉工具链 (2011.11.1),使用 gcc 4.6.2、glibc 2.14.1、binutils 2.21.1a、内核 2.6.39。
  • 与 2011.03.1 工具链(gcc 4.5.2/glibc 2.13/binutils 2.18/kernel 2.6.36)相同的板。

没有问题的平台:

  • 我们自己的 ARM 板,也运行 PTXDist Linux(32 位 2.6.29.6-rt23),使用 OSELAS arm-v4t 交叉工具链(1.99.3)和 gcc 4.3.2/glibc 2.8/binutils 2.18/内核2.6.27。
  • 我的笔记本电脑 (Intel Core i7),运行 64 位 Ubuntu 11.04(虚拟化/内核 2.6.38.15-generic),gcc 4.5.2/eglibc 2.13-0ubuntu13.1/binutils 2.21.0.20110327。

我一直在网上寻找解决方案,遇到了一些我试过但没有任何效果的补丁:

我们的代码是不是做错了,恰好在某些平台上工作,或者这是底层系统中的错误?如果有人知道在哪里查看,或者知道任何补丁或类似的尝试,我很乐意听到。

谢谢!

更新:

最佳答案

这已由 libc patch 修复. 我已经确认它可以在我自己的有问题的平台(我们的定制 AMD Fusion 板)上运行,修补到 glibc-2.14.1。

感谢 Siddhesh Poyarekar 的修复!

关于c++ - 取消 pthread_cond_wait() 挂起与 PRIO_INHERIT 互斥锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11878445/

相关文章:

c++ - 将结构作为多映射中的键传递时出错

c - 如何将客户端重定向到不同的 URL?

c++ - 基于 pthread 的多功能多线程实用程序库

c - 我在哪里得到这个总线错误?

c - 如何正确定义我的函数原型(prototype)?

c - OS X 上的 Pthread 和 gcc 编译问题

c++ - 使用从列表中弹出的 pthreads 填充大小的列表

c++ - 使用 lambda 将可变参数转发给线程

c++ - 如何检查堆栈是否未损坏

c++ - 读取 system() 命令错误响应消息