pthread_mutex_timedlock和死锁

时间:2011-09-07 10:15:54

标签: c linux posix

通常,如果task1持有锁A,则想要获取锁B而另一个任务2已经获取锁B并且正在等待由task1持有的锁A,这会导致死锁。

但是当涉及到pthread_mutex_timedlock时,它会在指定的超时后尝试互斥锁定或超时。

我遇到了僵局的情况,我试图采取定时锁定,这最终会超时,这让我很困惑。

编辑:通过更好的设计可以避免死锁,这是我最终做的,我确保采用互斥锁的顺序是相同的,以避免死锁 但是,由于我选择了timedlock

,因此可以避免死锁的问题仍未解决

有人能解释一下这种行为吗?

编辑:附加示例代码以使场景更清晰(实际任务相当复杂,并且可以运行数千行)

T1

pthread_mutex_lock(&lockA);
//call some API, which results in a lock of m2
pthread_mutex_lock(&lockB);
//unlock in the order
pthread_mutex_unlock(&lockB);
pthread_mutex_unlock(&lockA);

T2

pthread_mutex_lock(&lockB);
//call some API, which results in locking m1
pthread_mutex_timedlock(&lockA,<10 sec>); 

崩溃发生在T2,bt:

的背景下
Program terminated with signal 6, Aborted.
#0  0x57edada0 in raise () from /lib/libc.so.6
(gdb) bt
#0  0x57edada0 in raise () from /lib/libc.so.6
#1  0x57edc307 in abort () from /lib/libc.so.6
#2  0x57ed4421 in __assert_fail () from /lib/libc.so.6
#3  0x57bb2a7c in pthread_mutex_timedlock () from /lib/libpthread.so.0

我将错误追溯到以下

pthread_mutex_timedlock: Assertion `(-(e)) != 35 || (kind != PTHREAD_MUTEX_ERRORCHECK_NP && kind != PTHREAD_MUTEX_RECURSIVE_NP)' failed.

2 个答案:

答案 0 :(得分:2)

在glibc来源pthread_mutex_timedlock()中,这个断言看起来像这样:

    int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
                  __lll_private_flag (FUTEX_LOCK_PI,
                          private), 1,
                  abstime);
    if (INTERNAL_SYSCALL_ERROR_P (e, __err))
      {
    if (INTERNAL_SYSCALL_ERRNO (e, __err) == ETIMEDOUT)
      return ETIMEDOUT;

    if (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH
        || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK)
      {
        assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK
            || (kind != PTHREAD_MUTEX_ERRORCHECK_NP
            && kind != PTHREAD_MUTEX_RECURSIVE_NP));
        /* ESRCH can happen only for non-robust PI mutexes where
           the owner of the lock died.  */
        assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH
            || !robust);

e == EDEADLKkind可能是PTHREAD_MUTEX_ERRORCHECK_NPPTHREAD_MUTEX_RECURSIVE_NP。另一件需要注意的事情是在检查之前处理超时,即你没有达到超时。

在内核中,futex_lock_pi_atomic()返回EDEADLK代码:

 /*
  * Detect deadlocks.
  */
 if ((unlikely((curval & FUTEX_TID_MASK) == vpid)))
         return -EDEADLK;

 /*

上面的部分比较了锁定互斥锁的线程的TID和尝试获取互斥锁的线程的TID。如果它们是相同的,则表明该线程正在尝试获取它已经获取的互斥锁。

答案 1 :(得分:0)

首先,超时指定的时间是多少?它大吗?

pthread_mutex_timedlock在三个条件下失败 1 GT;检测到死锁条件或当前线程已拥有互斥锁。 2&gt;无法获取互斥锁,因为已超过互斥锁的最大递归锁定数。 3&gt; mutex指定的值不是指初始化的互斥对象。

您的代码是否受到上述任何操作。

此外,代码snipet可能有助于我们清楚地看到问题。