取消调用pthread_cond_wait()与PRIO_INHERIT互斥挂起(Cancellin

2019-06-26 22:12发布

更新4/10 2012: 由libc的补丁修复


我在取消线程的问题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年3月1日的工具链也(GCC 4.5.2 / glibc的2.13 / 2.18的binutils /内核2.6.36)。

平台,没有任何问题:

  • 我们自己的ARM板,还运行一个PTXDist的Linux(32位2.6.29.6-RT23),采用OSELAS臂-4T版交叉工具链(1.99.3)用gcc 4.3.2 / glibc的2.8 / 2.18的binutils /内核2.6.27 。
  • 我的笔记本电脑(英特尔酷睿i7),运行64位的Ubuntu 11.04(虚拟化/内核2.6.38.15,通用),GCC 4.5.2 / eglibc 2.13-0ubuntu13.1 / binutils的2.21.0.20110327。

我一直在寻找周围的净解决办法,和所遇到的,我已经尝试了几个补丁,但没有任何效果:

  • 制作条件变量优先级继承意识。
  • 从FUTEX_WAIT_REQUEUE_PI处理EAGAIN

难道我们做错事在我们的代码,这恰好在某些平台上工作,或者这是在底层系统中的错误? 如果任何人有什么地方看什么想法,或者任何补丁或类似尝试的人都知道,我很高兴听到这个消息。

谢谢!

更新:

  • libc中的帮助邮件列表讨论
  • glibc的bug报告

Answer 1:

此问题已修复由libc的补丁 。 我已经证实,它在我自己的问题的平台(我们的定制的AMD Fusion板),贴在glibc的-2.14.1工作。

由于外出Siddhesh Poyarekar的修复!



文章来源: Cancelling pthread_cond_wait() hangs with PRIO_INHERIT mutex