Требуется помощь в отладке pthreads - PullRequest
4 голосов
/ 14 июля 2010

У меня есть программа клиент-сервер, в которой есть несколько потоков как на сервере, так и на клиенте. Есть переменное количество клиентов и серверов (например, 3 сервера (реплики), 10 клиентов). Я отлаживаю исходный файл в этой программе. Я думаю, что есть какой-то тупик, возможно, следующий:

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

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

if (pthread_mutex_lock(&a_mutex) == EDEADLK) {
    cout<<"couldnt acquire lock."<<endl;
}
else cout<<"acquired lock"<<endl;

Я попытался отладить (подключив один запущенный серверный процесс) с помощью gdb. Я добавил «display» и «watch» (в разных прогонах gdb) для a_mutex. Я получаю результат следующей формы:

1: a_mutex = {__data = {__lock = 2, __count = 0, __owner = 4193, __kind = 0, __nusers = 2, 
{__spins = 0, __list = {__next = 0x0}}}, 
  __size = "\002\000\000\000\000\000\000\000a\020\000\000\000\000\000\000\002\000\000  \000\000\000\000", __align = 2}

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

#0  0xb8082430 in __kernel_vsyscall ()
#1  0xb7e347a6 in nanosleep () from /lib/tls/i686/cmov/libc.so.6
#2  0xb7e345be in sleep () from /lib/tls/i686/cmov/libc.so.6
#3  0x0804cb59 in class1::method1 (this=0xbfa9fe6c, clt=1, id=
    {static npos = 4294967295, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xb7c9c11c "l/%\b"}})
at file1.cc:33

Я не знаю, как и где ошибка.

Буду очень признателен за любую помощь по следующим вопросам:

  1. Каков хороший метод отладки таких условий / программ?
  2. Как определить состояние тупика (т. Е. Где блокировка удерживается и не снимается)?
  3. В такой многопроцессорной программе есть ли лучший способ использования gdb? (т.е. проверять состояния во всех процессах? настраивать gdb для просмотра / отображения переменной перед началом процесса?)
  4. Потому что, когда я присоединяю gdb к серверу после его запуска (по сценарию тестера), сервер может уже опередить код, который я хочу проверить. Я попытался добавить sleep (20) перед подозрительной областью, чтобы помочь мне с GDB, но я думаю, что это не очень хороший способ. Я также думаю, что открытие нескольких терминалов, запуск серверов и клиентов вручную и проверка состояния каждого из них также не очень хорошая идея (пожалуйста, исправьте меня, если я ошибаюсь).

PS: я прочитал этот вопрос уже.

Большое спасибо.

1 Ответ

4 голосов
/ 22 июля 2010

Используйте GDB и прикрепите его к зависшей программе. Тогда используйте "thread apply all bt" (думаю, но у меня нет удобной системы).

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

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

...