是否有可能确定持有互斥体的线程?
首先,我使用pthread库来编写multithreadingC程序。 线程总是挂在等待的互斥体上。 当我使用strace实用程序来查找一个线程处于FUTEX_WAIT
状态时,我想知道哪个线程在那个时候持有该互斥体。 但我不知道该怎么做。 有没有公用事业可以做到这一点?
有人告诉我,Java虚拟机支持这个,所以我想知道Linux是否支持这个function。
你可以使用互斥的内部知识来做到这一点。 通常这不是一个好主意,但是debugging很好。
在使用pthreads的NPTL实现(这是任何现代glibc)的Linux下,您可以检查pthread_mutex_t
结构的__data.__owner
成员以找出当前已locking的线程。 在用gdb
连接到进程之后,这是怎么做的:
(gdb) thread 2 [Switching to thread 2 (Thread 0xb6d94b90 (LWP 22026))]#0 0xb771f424 in __kernel_vsyscall () (gdb) bt #0 0xb771f424 in __kernel_vsyscall () #1 0xb76fec99 in __lll_lock_wait () from /lib/i686/cmov/libpthread.so.0 #2 0xb76fa0c4 in _L_lock_89 () from /lib/i686/cmov/libpthread.so.0 #3 0xb76f99f2 in pthread_mutex_lock () from /lib/i686/cmov/libpthread.so.0 #4 0x080484a6 in thread (x=0x0) at mutex_owner.c:8 #5 0xb76f84c0 in start_thread () from /lib/i686/cmov/libpthread.so.0 #6 0xb767784e in clone () from /lib/i686/cmov/libc.so.6 (gdb) up 4 #4 0x080484a6 in thread (x=0x0) at mutex_owner.c:8 8 pthread_mutex_lock(&mutex); (gdb) print mutex.__data.__owner $1 = 22025 (gdb)
(我切换到挂起的线程,做一个回溯find它卡住的pthread_mutex_lock()
;改变堆栈帧来找出它试图locking的互斥体的名称;然后打印该互斥体的所有者。 这告诉我,线程号为22025的线程是罪魁祸首。
我不知道任何这样的设施,所以我不认为你会轻易下车 – 这可能不会像你想的那样帮助debugging你的程序。 由于看起来技术含量低,伐木是你debugging这些东西的朋友。 开始收集你自己的小日志function。 他们不必花哨,他们只需要在debugging的时候完成工作。
抱歉的C ++,但是像这样的:
void logit(const bool aquired, const char* lockname, const int linenum) { pthread_mutex_lock(&log_mutex); if (! aquired) logfile << pthread_self() << " tries lock " << lockname << " at " << linenum << endl; else logfile << pthread_self() << " has lock " << lockname << " at " << linenum << endl; pthread_mutex_unlock(&log_mutex); } void someTask() { logit(false, "some_mutex", __LINE__); pthread_mutex_lock(&some_mutex); logit(true, "some_mutex", __LINE__); // do stuff ... pthread_mutex_unlock(&some_mutex); }
logging不是一个完美的解决scheme,但没有。 它通常会让你知道你需要的东西。
通常,libc / platforms调用是由操作系统抽象层抽象的。 可以使用所有者variables和pthread_mutex_timedlock来跟踪互斥锁死锁。 每当线程locking时,它应该用自己的tid(gettid())更新variables,并且还可以为pthread id存储设置另一个variables。 所以当其他线程在pthread_mutex_timedlock上阻塞并超时时,它可以打印owner tid和pthread_id的值。 这样你可以很容易地找出所有者线程。 请find下面的代码片段,注意不处理所有的错误条件
pid_t ownerTid; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; class TimedMutex { public: TimedMutex() { struct timespec abs_time; while(1) { clock_gettime(CLOCK_MONOTONIC, &abs_time); abs_time.tv_sec += 10; if(pthread_mutex_timedlock(&mutex,&abs_time) == ETIMEDOUT) { log("Lock held by thread=%d for more than 10 secs",ownerTid); continue; } ownerTid = gettid(); } } ~TimedMutex() { pthread_mutex_unlock(&mutex); } };
还有其他的方法来查找死锁,也许这个链接可能会帮助http://yusufonlinux.blogspot.in/2010/11/debugging-core-using-gdb.html 。
请阅读下面的链接,这有一个寻找锁拥有者的通用解决scheme。 它即使锁在一个库中也没有源代码。
https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Deadlocks