Linux 是否可以确定持有互斥锁的线程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3483094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 20:21:32  来源:igfitidea点击:

Is it possible to determine the thread holding a mutex?

clinuxmultithreadingpthreadsmutex

提问by terry

Firstly, I use pthread library to write multithreading C program. Threads always hung by their waited mutexs. When I use the strace utility to find a thread is in FUTEX_WAITstatus, I want to know which thread hold that mutex at the time. But I don't know how could I make it. Are there any utilities could do that?

首先,我使用 pthread 库编写多线程 C 程序。线程总是被等待的互斥锁挂起。当我使用 strace 实用程序查找处于FUTEX_WAIT状态的线程时,我想知道当时哪个线程持有该互斥锁。但我不知道我怎么能做到。是否有任何实用程序可以做到这一点?

Someone told me Java virtual machine support this, so I want to know whether Linux support this feature.

有人告诉我Java虚拟机支持这个,所以我想知道Linux是否支持这个功能。

回答by Duck

I don't know of any such facility so I don't think you will get off that easily - and it probably wouldn't be as informative as you think in helping to debug your program. As low tech as it might seem, logging is your friend in debugging these things. Start collecting your own little logging functions. They don't have to be fancy, they just have to get the job done while debugging.

我不知道有任何这样的工具,所以我认为你不会那么容易下车——而且它可能不会像你想象的那样有助于调试你的程序。尽管看起来技术含量很低,但在调试这些东西时,日志记录是您的朋友。开始收集您自己的小日志功能。他们不必花哨,他们只需要在调试时完成工作。

Sorry for the C++ but something like:

对不起 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 isn't a perfect solution but nothing is. It usually gets you what you need to know.

日志记录不是一个完美的解决方案,但什么都不是。它通常会为您提供您需要了解的信息。

回答by caf

You can use knowledge of the mutex internals to do this. Ordinarily this wouldn't be a very good idea, but it's fine for debugging.

您可以使用互斥锁内部知识来执行此操作。通常这不是一个很好的主意,但它可以用于调试。

Under Linux with the NPTL implementation of pthreads (which is any modern glibc), you can examine the __data.__ownermember of the pthread_mutex_tstructure to find out the thread that currently has it locked. This is how to do it after attaching to the process with gdb:

在具有 pthreads 的 NPTL 实现(任何现代 glibc)的 Linux 下,您可以检查__data.__ownerpthread_mutex_t结构的成员以找出当前锁定它的线程。这是附加到进程后的方法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
 = 22025
(gdb)

(I switch to the hung thread; do a backtrace to find the pthread_mutex_lock()it's stuck on; change stack frames to find out the name of the mutex that it's trying to lock; then print the owner of that mutex). This tells me that the thread with LWP ID 22025 is the culprit.

(我切换到挂起的线程;进行回溯以找到pthread_mutex_lock()它被卡住的线程;更改堆栈帧以找出它试图锁定的互斥锁的名称;然后打印该互斥锁的所有者)。这告诉我 LWP ID 为 22025 的线程是罪魁祸首。

You can then use thread find 22025to find out the gdbthread number for that thread and switch to it.

然后,您可以使用thread find 22025找出该gdb线程的线程编号并切换到该线程。

回答by Yusuf Khan

Normally libc/platforms calls are abstracted by OS abstraction layer. The mutex dead locks can be tracked using a owner variable and pthread_mutex_timedlock. Whenever the thread locks it should update the variable with own tid(gettid() and can also have another variable for pthread id storage) . So when the other threads blocks and timed out on pthread_mutex_timedlock it can print the value of owner tid and pthread_id. this way you can easily find out the owner thread. please find the code snippet below, note that all the error conditions are not handled

通常 libc/platforms 调用由操作系统抽象层抽象。可以使用所有者变量和 pthread_mutex_timedlock 跟踪互斥锁死锁。每当线程锁定时,它应该使用自己的 tid(gettid() 更新变量,并且还可以有另一个变量用于 pthread id 存储)。因此,当其他线程在 pthread_mutex_timedlock 上阻塞并超时时,它可以打印所有者 tid 和 pthread_id 的值。这样您就可以轻松找到所有者线程。请找到下面的代码片段,注意所有的错误条件都没有处理

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);  
        }
};

There are other ways to find out dead locks, maybe this link might help http://yusufonlinux.blogspot.in/2010/11/debugging-core-using-gdb.html.

还有其他方法可以找出死锁,也许这个链接可能对http://yusufonlinux.blogspot.in/2010/11/debugging-core-using-gdb.html有所帮助。

回答by Jossy Sebastian

Please read below link, This has a generic solution for finding the lock owner. It works even if lock in side a library and you don't have the source code.

请阅读下面的链接,这是找到锁所有者的通用解决方案。即使锁定在库中并且您没有源代码,它也可以工作。

https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Deadlocks

https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Deadlocks