Ошибка утверждения мьютекса Pthread

Я сталкиваюсь со следующей ошибкой в ​​непредсказуемое время в коммуникационном приложении на базе Linux (arm):

pthread_mutex_lock.c:82: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.

Google выдает много ссылок на эту ошибку, но мало информации, имеющей отношение к моей ситуации. Мне было интересно, может ли кто-нибудь дать мне несколько идей о том, как устранить эту ошибку. Кто-нибудь знает общую причину этого утверждения?

Заранее спасибо.


person Dave Causey    schedule 09.07.2009    source источник
comment
Исключив все другие возможности, я решил инвестировать в RTFM. Похоже, я использовал мьютекс способом, который официально не поддерживается. Когда поток ожидает какого-либо внешнего стимула, он ожидает своего мьютекса. Поток возвращается к жизни, когда мьютекс освобождается, всегда из другого потока. Таким образом, освобождающий поток никогда не является владельцем мьютекса. Я изменил реализацию, чтобы использовать переменную условия. Я пока не знаю, является ли это причиной моих бед. Я (неправильно) использовал мьютекс таким образом в течение многих лет и до сих пор не имел с ним никаких проблем.   -  person Dave Causey    schedule 10.07.2009
comment
Разве pthread_mutexes (и вообще мьютексы) не задокументированы таким образом, что они должны быть разблокированы тем же потоком, который их заблокировал? Тот факт, что он работает на других платформах, зависит от реализации и не является переносимым.   -  person ephemient    schedule 10.07.2009
comment
Я думаю, что это то, что я сказал в своем комментарии выше. Моя реализация неправильно использовала мьютекс, поэтому я изменил его, чтобы правильно использовать переменную условия. Остается лишь подтвердить, что именно это и стояло за прерывистым утверждением.   -  person Dave Causey    schedule 11.07.2009
comment
Иногда у меня возникает та же ошибка, когда мой мьютекс неправильно инициализируется --> используйте pthread_mutex_init   -  person Chris Maes    schedule 27.05.2015


Ответы (8)


Непоколебимый 4 дня подряд. Я объявляю победу на этом. Ответ — «глупая ошибка пользователя» (см. комментарии выше). Мьютекс должен быть разблокирован только тем потоком, который его заблокировал. Спасибо, что терпели меня.

person Dave Causey    schedule 13.07.2009
comment
Тогда ваше решение применимо только к разблокировке, верно? Я получаю ту же ошибку при попытке заблокировать его. - person User; 27.11.2017

TLDR: убедитесь, что вы не блокируете мьютекс, который был уничтожен/не был инициализирован.

Хотя у ОП есть свой ответ, я подумал, что поделюсь своей проблемой на случай, если у кого-то еще возникнет та же проблема, что и у меня.

Обратите внимание, что утверждение находится в __pthread_mutex_lock, а не в разблокировке. Для меня это говорит о том, что большинство других людей, сталкивающихся с этой проблемой, не разблокируют мьютекс в другом потоке, чем тот, который его заблокировал; они просто блокируют мьютекс, который был уничтожен.

Для меня у меня был класс (назовем его Foo), который зарегистрировал статическую функцию обратного вызова с каким-то другим классом (назовем его Bar). Обратный вызов передавал ссылку на Foo и иногда блокировал/разблокировал мьютекс, который был членом Foo.

Эта проблема возникла после того, как экземпляр Foo был уничтожен, когда экземпляр Bar все еще использовал обратный вызов. Обратному вызову передавалась ссылка на объект, который больше не существует, и, следовательно, вызывал __pthread_mutex_lock для мусорной памяти.

Обратите внимание: я использовал std::mutex и std::lock_guard<std::mutex> из С++ 11, но, поскольку я работал в Linux, проблема была точно такой же.

person rationalcoder    schedule 09.04.2017
comment
Чтобы добавить к этому, у меня это произошло, когда я дважды открывал один и тот же замок. Ошибка утверждения произошла в следующий раз, когда я пытался получить блокировку, что немного усложнило ее поиск. - person HashFail; 06.05.2019

Я столкнулся с той же проблемой, и Google отправил меня сюда. Проблема с моей программой заключалась в том, что в некоторых ситуациях я не инициализировал мьютекс перед его блокировкой.

Хотя утверждение в принятом ответе является законным, я думаю, что это не причина этого неудавшегося утверждения. Потому что об ошибке сообщается pthread_mutex_lockне разблокировка).

Также, как всегда, более вероятно, что ошибка находится в исходном коде программиста, а не в компиляторе.

person Shayan Pooya    schedule 15.11.2011

Быстрый поиск в Google, который я сделал, часто обвиняет в этом неправильную оптимизацию компилятора. Подведение итогов можно найти здесь. Возможно, стоит взглянуть на вывод сборки, чтобы убедиться, что gcc создает правильный код.

Либо так, либо вам удается топать память, используемую библиотекой pthread... такие проблемы довольно сложно найти.

person Chris Arguin    schedule 09.07.2009
comment
Я был на пути неправильной оптимизации компилятора, что, по-видимому, не является проблемой в данном случае: assert (mutex-›__data.__owner == 0); 154: e5953008 ldr r3, [r5, #8] 158: e3530000 cmp r3, #0 ; 0x0 15c: 1a0001a0 bne 7e4 ‹__pthread_mutex_lock+0x7e4› - person Dave Causey; 09.07.2009

у меня была такая же проблема

в моем случае внутри потока я подключал vertica db к odbc, добавляя следующие настройки в /etc/odbcinst.ini, что решило мою проблему. пока не получаю исключения.

[ODBC]
Threading = 1

кредиты: hynek

person ismail    schedule 05.02.2015

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

Проблема в этом случае заключалась в том, что базовый класс создавал поток в конструкторе. Затем поток начал выполняться, и была вызвана реализация метода производных классов. К сожалению, производный класс еще не завершил построение, и мьютекс в производном классе имел неинициализированные данные в качестве владельца мьютекса. Из-за этого казалось, что он на самом деле заблокирован, когда это не так.

Решение действительно простое. Добавьте в базовый класс защищенный метод StartThread(). Это нужно вызывать в конструкторе производных классов, а не из базового класса.

person ReefSmacker    schedule 23.07.2019

Если вы используете C++ и std::unique_lock, проверьте этот ответ: https://stackoverflow.com/a/9240466/9057530

person yyFred    schedule 23.02.2021
comment
вы имеете в виду std::unique_lock - person mark; 02.06.2021
comment
@отметьте, вы правы. Я изменил свой ответ. - person yyFred; 03.06.2021
comment
@yyFred У вас все еще есть небольшая опечатка. Я предполагаю, что это должно быть unique вместо unqiue. Просто говорю. Хорошего дня! - person Nope; 11.06.2021

добавление Threading=0 в файл /etc/odbcinst.ini устранило эту проблему.

person stanley emmanuel    schedule 14.09.2016