infinite abort() в обратном вызове дампа ядра программы на C++

У меня странная проблема, которую я не могу решить. Пожалуйста помоги!

Программа представляет собой многопоточное приложение на C++, работающее на компьютере с ARM Linux. Недавно я начал тестировать его на длительные прогоны, и иногда он вылетает через 1-2 дня, например так:

*** glibc detected ** /root/client/my_program: free(): invalid pointer: 0x002a9408 ***

Когда я открываю дамп ядра, я вижу, что основной поток, кажется, имеет поврежденный стек: все, что я вижу, бесконечно abort() вызовов.

GNU gdb (GDB) 7.3 
...
This GDB was configured as "--host=i686 --target=arm-linux".
[New LWP 706]
[New LWP 700]
[New LWP 702]
[New LWP 703]
[New LWP 704]
[New LWP 705]
Core was generated by `/root/client/my_program'.
Program terminated with signal 6, Aborted.
#0  0x001c44d4 in raise ()
(gdb) bt
#0  0x001c44d4 in raise ()
#1  0x001c47e0 in abort ()
#2  0x001c47e0 in abort ()
#3  0x001c47e0 in abort ()
#4  0x001c47e0 in abort ()
#5  0x001c47e0 in abort ()
#6  0x001c47e0 in abort ()
#7  0x001c47e0 in abort ()
#8  0x001c47e0 in abort ()
#9  0x001c47e0 in abort ()
#10 0x001c47e0 in abort ()
#11 0x001c47e0 in abort ()

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

Когда я просматриваю другие темы, там все вроде нормально.

(gdb) info threads
  Id   Target Id         Frame 
  6    LWP 705           0x00132f04 in nanosleep ()
  5    LWP 704           0x001e7a70 in select ()
  4    LWP 703           0x00132f04 in nanosleep ()
  3    LWP 702           0x00132318 in sem_wait ()
  2    LWP 700           0x00132f04 in nanosleep ()
* 1    LWP 706           0x001c44d4 in raise ()
(gdb) thread 5
[Switching to thread 5 (LWP 704)]
#0  0x001e7a70 in select ()
(gdb) bt
#0  0x001e7a70 in select ()
#1  0x00057ad4 in CSerialPort::read (this=0xbea7d98c, string_buffer=..., delimiter=..., timeout_ms=1000) at CSerialPort.cpp:202
#2  0x00070de4 in CScanner::readResponse (this=0xbea7d4cc, resp_recv=..., timeout=1000, delim=...) at PidScanner.cpp:657
#3  0x00071198 in CScanner::sendExpect (this=0xbea7d4cc, cmd=..., exp_str=..., rcv_str=..., timeout=1000) at PidScanner.cpp:604
#4  0x00071d48 in CScanner::pollPid (this=0xbea7d4cc, mode=1, pid=12, pid_str=...) at PidScanner.cpp:525
#5  0x00072ce0 in CScanner::poll1 (this=0xbea7d4cc) 
#6  0x00074c78 in CScanner::Poll (this=0xbea7d4cc) 
#7  0x00089edc in CThread5::Thread5Poll (this=0xbea7d360) 
#8  0x0008c140 in CThread5::run (this=0xbea7d360) 
#9  0x00088698 in CThread::threadFunc (p=0xbea7d360) 
#10 0x0012e6a0 in start_thread ()
#11 0x001e90e8 in clone ()
#12 0x001e90e8 in clone ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

(Названия классов и функций немного странные, потому что я их изменил -:) Таким образом, стек поврежден в потоке №1, обратная трассировка всех остальных (2-6) показывает

Backtrace stopped: previous frame identical to this frame (corrupt stack?).

Это происходит из-за того, что потоки 2-6 создаются в потоке №1.

Дело в том, что я не могу запустить программу в gdb, потому что она работает на встроенной системе. Я не могу использовать удаленный сервер gdb. Единственный вариант — исследовать дампы ядра, которые встречаются не очень часто.

Не могли бы вы предложить что-нибудь, что могло бы меня продвинуть вперед? (Может быть, что-то еще я могу извлечь из дампа ядра или, может быть, как-то сделать некоторые хуки в коде, чтобы поймать вызов abort()).

ОБНОВЛЕНИЕ: Василий Старынкевич предложил использовать Valgrind, но оказалось, что он портирован только для ARMv7. У меня ARM 926, то есть ARMv5, так что мне это не подойдет.Есть некоторые попытки скомпилировать valgrind для ARMv5: Кросс-компиляция Valgrind для ARMv5tel, valgrind на ARM9

ОБНОВЛЕНИЕ 2: Не удалось заставить Electric Fence работать с моей программой. Программа использует C++ и pthreads. Версия Efence, которую я получил, 2.1.13 зависала в произвольном месте после того, как я запустил поток и попытался сделать что-то более или менее сложное (например, поместить значение в вектор STL). Я видел, как люди упоминали некоторые патчи для Efence в Интернете, но у меня не было времени их попробовать. Я попробовал это на своем ПК с Linux, а не на ARM, и другие инструменты, такие как valgrind или Dmalloc, не сообщают о каких-либо проблемах с кодом. Итак, все, кто использует efence версии 2.1.13, должны быть готовы к проблемам с pthreads (или, может быть, pthread + C++ + STL, не знаю).

10
задан ks1322 25 March 2018 в 12:59
поделиться