У меня есть программа клиент-сервер, в которой есть несколько потоков как на сервере, так и на клиенте. Есть переменное количество клиентов и серверов (например, 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
Я не знаю, как и где ошибка.
Буду очень признателен за любую помощь по следующим вопросам:
- Каков хороший метод отладки таких условий / программ?
- Как определить состояние тупика (т. Е. Где блокировка удерживается и не снимается)?
- В такой многопроцессорной программе есть ли лучший способ использования gdb? (т.е. проверять состояния во всех процессах? настраивать gdb для просмотра / отображения переменной перед началом процесса?)
- Потому что, когда я присоединяю gdb к серверу после его запуска (по сценарию тестера), сервер может уже опередить код, который я хочу проверить. Я попытался добавить sleep (20) перед подозрительной областью, чтобы помочь мне с GDB, но я думаю, что это не очень хороший способ. Я также думаю, что открытие нескольких терминалов, запуск серверов и клиентов вручную и проверка состояния каждого из них также не очень хорошая идея (пожалуйста, исправьте меня, если я ошибаюсь).
PS: я прочитал этот вопрос уже.
Большое спасибо.