c ++ правильное использование мьютекса - PullRequest
3 голосов
/ 29 апреля 2011

У меня есть многопоточный проект, и я запустил его через valgrind с --tool = helgrind, и он показал мне несколько ошибок. Я использую мьютекс там как раз, как я нашел в сети, как его использовать, не могли бы вы показать мне, что не так?

#include <iostream>
#include <pthread.h>

#define MAX_THREADS     100
#define MAX_SESSIONS    100

static pthread_mutex_t  M_CREATE_SESSION_LOCK= PTHREAD_MUTEX_INITIALIZER;


.....



void connection::proccess(threadVarsType &THREAD) {
    ....

    pthread_mutex_lock(&M_CREATE_SESSION_LOCK);

    unsigned int ii;
    for (ii=0; ii<MAX_SESSIONS; ii++) {
        if (SESSION[ii]==NULL) {
            break;
        }
    }
    if (ii==MAX_SESSIONS-1) {
        ....
        pthread_mutex_unlock(&M_CREATE_SESSION_LOCK);                       // unlock session mutex
        ....
        return;
    } else {
        ....
        pthread_mutex_unlock(&M_CREATE_SESSION_LOCK);                       // unlock session mutex
        ....
    }

    ....
}

и сообщения об ошибках:

==4985== Thread #1's call to pthread_mutex_lock failed
==4985==    with error code 22 (EINVAL: Invalid argument)
    ....
==4985== Thread #1 unlocked an invalid lock at 0x4E7B40
==4985==    at 0x32CD8: pthread_mutex_unlock (hg_intercepts.c:610)
    ....
==4985== Thread #1's call to pthread_mutex_unlock failed
==4985==    with error code 22 (EINVAL: Invalid argument)
    ....
==4985== Thread #1's call to pthread_mutex_lock failed
==4985==    with error code 22 (EINVAL: Invalid argument)
    ....
==4985== Thread #1 unlocked an invalid lock at 0x4E7B40
==4985==    at 0x32CD8: pthread_mutex_unlock (hg_intercepts.c:610)
    ....
==4985== Thread #1's call to pthread_mutex_unlock failed
==4985==    with error code 22 (EINVAL: Invalid argument)

Ответы [ 4 ]

4 голосов
/ 29 апреля 2011

Во-первых, всегда проверяйте возвращаемые значения вызовов вашей функции.Если вызов pthread завершится неудачно, будет хорошим выбором просто вызвать abort(), который выполнит дамп памяти, если он у вас включен, или перейдет в отладчик, если вы работаете с ним.

Вызов функции pthread действительно долженникогда не ошибайтесь, а это значит, что с вашей программой что-то не так.В программах на C или C ++ то, что обычно вызывает таинственные сбои, - это повреждение памяти.Для проверки используйте valgrind в его обычных режимах.

Еще одна вещь, которая может вызвать сбой вызовов pthread, - это не компилировать с использованием -pthread.Если вы используете GCC, вы должны скомпилировать и связать, используя gcc, с помощью команды типа gcc -pthread.Это свяжет библиотеку pthread и установит некоторые определения препроцессора, которые могут быть важны для заголовочных файлов вашей системы.

Некоторые системы будут успешно компилировать и связывать программу, использующую вызовы pthread, без привязки ее к библиотекам pthread,Это сделано для того, чтобы программа или библиотека могли быть поточно-ориентированными без фактического использования потоков.Вызовы потоков будут связаны с фиктивными функциями, если не связана реальная библиотека pthread.Это может привести к сбою некоторых вызовов функций.

Поэтому убедитесь, что вы строите с правильными опциями компилятора для включения библиотек pthread.

Другая возможная причина - если вы строите на некотором сбитомиз полу-гибридной ОС, где она начиналась как Linux 2.4 и в какой-то момент была обновлена ​​до Linux 2.6 NPTL (однажды я работал над чем-то вроде этого).Если вы пытаетесь скомпилировать старые файлы заголовков с устаревшим определением PTHREAD_MUTEX_INITIALIZER или неправильным размером для типа pthread_mutex_t, это может вызвать проблему.

2 голосов
/ 30 апреля 2011

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

Вот что они пишут:

Проверка ошибок Helgrind не работает правильно внутри системы пронизывает сама библиотека (libpthread.so), и это обычно наблюдает большое количество (ложные) ошибки там. valgrind для Система подавления затем фильтрует эти вне, так что вы не должны их видеть.

Если вы видите какие-либо сообщения об ошибках гонки где libpthread.so или ld.so это объект, связанный с самым внутренним кадр стека, пожалуйста, отправьте отчет об ошибке в http://www.valgrind.org/.

Они также отмечают, что вы должны использовать «поддерживаемый дистрибутив Linux» ... они не упоминают, что именно это означает, но если вы используете ОС не из Linux, это также может вызвать некоторые из этих «ложные срабатывания». Возможно, стоит попросить команду разработчиков узнать, что они говорят по этому поводу.

2 голосов
/ 29 апреля 2011

Эта ошибка говорит о том, что что-то не так с инициализацией мьютекса.Трудно найти что, но убедитесь, что вы инициализируете его в нужном месте.

0 голосов
/ 29 апреля 2011

Ошибка EINVAL при вызове pthread_mutex_lock означает одну из двух вещей.

The mutex was created with the protocol attribute having the value PTHREAD_PRIO_PROTECT and the calling thread's priority is higher than the mutex's current priority ceiling.

или

The value specified by mutex does not refer to an initialised mutex object.

Второй кажется более вероятным.Попробуйте инициализировать мьютекс в вашей функции main с помощью int error = pthread_mutex_init(&M_CREATE_SESSION_LOCK, NULL); и проверьте, есть ли ошибка, вместо того, чтобы инициализировать его макросом, как в данный момент.

...