pthread_recursive_mutex - утверждение не удалось - PullRequest
0 голосов
/ 07 мая 2020

Я использую фреймворк ROS (операционная система роботов). Если вы знакомы с ROS, в моем коде я не использую серверы активности. Толком пользуются издатели, подписчики и сервисы. К сожалению, я столкнулся с проблемой pthread_recursive_mutex. Ниже приводится ошибка и ее обратная трассировка.

Если кто-нибудь знаком со стеком ROS, не могли бы вы рассказать, какие могут быть потенциальные причины, которые могут вызвать эту ошибку времени выполнения?

Я могу предоставить дополнительную информацию по поводу моей ошибки выполнения. Помощь очень ценится. Спасибо

/usr/include/boost/thread/pthread/recursive_mutex.hpp:113: void boost::recursive_mutex::lock(): Assertion `!pthread_mutex_lock(&m)' failed.

enter image description here

Ответы [ 2 ]

0 голосов
/ 08 мая 2020

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

Мне удалось использовать Valgrind для поиска ошибок этого типа. Установите его, используя apt install valgrind, и добавьте launch-prefix="valgrind" к <node> в вашем файле запуска. Он будет очень медленным, но достаточно искусным в выявлении этих проблем.

Возьмем, к примеру, эту программу с ошибками:

struct Test
{
    int a;
};

int main()
{
    Test* test = new Test();
    test->a = 42;
    delete test;
    test->a = 0; // BUG!
}

valgrind ./testprog дает

==8348== Invalid write of size 4
==8348==    at 0x108601: main (test.cpp:11)
==8348==  Address 0x5b7ec80 is 0 bytes inside a block of size 4 free'd
==8348==    at 0x4C3168B: operator delete(void*, unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==8348==    by 0x108600: main (test.cpp:10)
==8348==  Block was alloc'd at
==8348==    at 0x4C303EF: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==8348==    by 0x1085EA: main (test.cpp:8)

Обратите внимание, как он не только сообщит вам, где произошел ошибочный доступ (test.cpp:11), но также и где объект Test был удален (test.cpp:10) и где он был первоначально создан (test.cpp:8).

Удачи в поиске ошибок!

0 голосов
/ 08 мая 2020

Реализация метода lock просто подтверждает возвращаемое значение pthread:

    void lock()
    {
        BOOST_VERIFY(!posix::pthread_mutex_lock(&m));
    }

Это означает, что в соответствии с документами:

  • (EAGAIN) Не удалось получить мьютекс, потому что было превышено максимальное количество рекурсивных блокировок для мьютекса. гарантирует, что этого не произойдет) или просто собирают потоки, которые все ждут одной и той же блокировки

  • (EOWNERDEAD) Мьютекс - это надежный мьютекс, а процесс, содержащий предыдущий поток-владелец завершился, удерживая блокировку мьютекса. Блокировка мьютекса должна быть получена вызывающим потоком, и новый владелец должен сделать состояние согласованным.

    Boost не работает с этим случаем и просто утверждает. Это также вряд ли произойдет, если все ваши потоки будут использовать поточно-безопасные блокировки (scoped_lock, unique_lock, shared_lock, lock_guard). Однако это может произойти, если вы где-то вручную используете функции lock()unlock()), а поток завершится без unlock() ing

Есть другие способы которые (особенно проверенные) мьютексы могут выйти из строя, но они не будут применяться к boost::recursive_mutex

...