C++ 取消pthread_cond_wait()与PRIO_INHERIT mutex挂起

C++ 取消pthread_cond_wait()与PRIO_INHERIT mutex挂起,c++,c,pthreads,mutex,embedded-linux,C++,C,Pthreads,Mutex,Embedded Linux,更新,2012年4月10日: 我在取消pthread\u cond\u wait中使用带有pthread\u PRIO\u INHERIT属性集的互斥体的线程时遇到问题。但这只发生在某些平台上 下面的示例演示了这一点:(使用g++.cpp-lpthread编译) 如果未在互斥锁上设置PTHREAD\u PRIO\u INHERIT,则一切正常,程序将干净地退出 有问题的平台: 嵌入式AMD Fusion板,运行基于32位Linux的3.2.9-rt16(带16)。我们正在使用最新的i686

更新,2012年4月10日:


我在取消
pthread\u cond\u wait
中使用带有
pthread\u PRIO\u INHERIT
属性集的互斥体的线程时遇到问题。但这只发生在某些平台上

下面的示例演示了这一点:(使用
g++.cpp-lpthread编译)

如果未在互斥锁上设置
PTHREAD\u PRIO\u INHERIT
,则一切正常,程序将干净地退出

有问题的平台:

  • 嵌入式AMD Fusion板,运行基于32位Linux的3.2.9-rt16(带16)。我们正在使用最新的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/kernel 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
我一直在网上寻找解决方案,遇到了一些我尝试过的补丁,但没有任何效果:

我们的代码中是否有错误,只是碰巧在某些平台上工作,或者这是底层系统中的错误?如果有人知道去哪里找,或者知道有补丁或类似的东西可以试用,我很乐意听到

谢谢

更新:

这一问题已由一家公司解决。 我已经确认它可以在我自己的有问题的平台(我们的定制AMD Fusion板)上工作,该平台被补丁到glibc-2.14.1上


感谢Siddhesh Poyarekar的修复

pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock,(void*)&mutex)已损坏。不能像那样强制转换函数指针。您需要编写一个包装器函数并传递包装器的地址。(顺便说一句,在我的Linux机器上,这在64位程序中有效,但在32位程序中失败。无论
pthread\u mutex\u unlock
是否正确包装,这都是正确的。)感谢您的回答,我已经更新了代码示例,使用包装器-遗憾的是,这对我们的嵌入式电路板都没有影响(仍然不工作,从未进入清理处理程序)和我的笔记本电脑(仍然工作,运行清理正常)。有趣的是,它可以在64位上工作,但不能在32位上工作,我将对此进行研究。@David,它是UB,是的,但在x86_64的情况下,它不是破坏它的原因。参数号、寄存器类型和表示匹配。我怀疑这可能与glibc(NPTL)有关错误号14417:嗯……这听起来并不令人鼓舞。如果你有关于这个话题的任何讨论或类似的链接,我会非常感兴趣的!
#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;
}
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