pthread_mutex_timedlock и тупик - PullRequest
       0

pthread_mutex_timedlock и тупик

2 голосов
/ 07 сентября 2011

Как правило, если задача1 удерживает блокировку A, хочет захватить блокировку B, а другая задача2 взяла блокировку B и ожидает блокировки A, удерживаемой задачей1), это вызывает тупик.

Но когда дело доходит доpthread_mutex_timedlock, он пытается выполнить блокировку мьютекса или тайм-аут после указанного тайм-аута.

Я попал в сценарий тупиковой ситуации, в котором я пытался взять тайм-блокировку, которая в конечном итоге истекла бы, что озадачивает меня.1006 * edit: можно избежать тупиков, имея лучший дизайн, что я и сделал в итоге, я убедился, что порядок взятия блокировок мьютекса одинаков, чтобы избежать тупиков, но остается открытым вопрос о том,тупика можно избежать, так как я выбрал временную блокировку

Может кто-нибудь объяснить мне это поведение?

Редактировать: Прикрепить пример кода, чтобы сделать сценарий более ясным (реальные задачи довольносложный и работает в тысячи строк)

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 ]

2 голосов
/ 07 сентября 2011

В источниках 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 == EDEADLK и kind равны PTHREAD_MUTEX_ERRORCHECK_NP или PTHREAD_MUTEX_RECURSIVE_NP.Еще одна вещь, на которую следует обратить внимание, это то, что тайм-аут обрабатывается до этой проверки, т. Е. Вы не устанавливаете таймаут.

В ядре это futex_lock_pi_atomic(), возвращающий код EDEADLK:

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

 /*

В приведенном выше примере сравниваются TID потока, который заблокировал мьютекс, и TID потока, который пытается получить мьютекс.Если они одинаковы, это говорит о том, что поток пытается получить мьютекс, который он уже получил.

0 голосов
/ 07 сентября 2011

Прежде всего, сколько времени было указано на время ожидания?Это было большое?

pthread_mutex_timedlock завершается ошибкой в ​​трех условиях: 1> Обнаружено состояние взаимоблокировки или текущий поток уже владеет мьютексом.2> Мьютекс не может быть получен, так как было превышено максимальное количество рекурсивных блокировок для мьютекса.3> Значение, указанное в mutex, не относится к инициализированному объекту mutex.

Ваш код подвергся какому-либо из перечисленного.

Также фрагмент кода может помочь разобратьсяувидеть проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...