更新、2012 年 4 月 10 日: 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
、すべてが正常に機能し、プログラムは正常に終了します。
問題のあるプラットフォーム:
- PTXDistベースの 32 ビット Linux 3.2.9-rt16 ( RTpatch 16 を使用)を実行する組み込み AMD Fusion ボード。gcc 4.6.2、glibc 2.14.1、binutils 2.21.1a、カーネル 2.6.39を使用して、最新のOSELAS i686 クロス ツールチェーン (2011.11.1) を使用しています。
- 2011.03.1 ツールチェーンと同じボード (gcc 4.5.2 / glibc 2.13 / binutils 2.18 / カーネル 2.6.36)。
問題のないプラットフォーム:
- Gcc 4.3.2 / glibc 2.8 / binutils 2.18 / カーネル 2.6.27 で OSELAS arm-v4t クロス ツールチェーン (1.99.3) を使用して、PTXDist Linux (32 ビット 2.6.29.6-rt23) も実行する独自の ARM ボード.
- 64 ビット Ubuntu 11.04 (仮想化 / カーネル 2.6.38.15-generic)、gcc 4.5.2 / eglibc 2.13-0ubuntu13.1 / binutils 2.21.0.20110327 を実行している私のラップトップ (Intel Core i7)。
私は解決策を求めてネットを見回しており、いくつかのパッチを試してみましたが、何の効果もありませんでした:
特定のプラットフォームでたまたま機能するコードで何か間違ったことをしているのですか、それとも基盤となるシステムのバグですか? 誰かがどこを見ればよいか、または試してみるためのパッチなどを知っている場合は、喜んでお知らせします.
ありがとう!
アップデート: