Ответ 1
Благодаря Адитья Кумару; приемлемое решение:
gdb -batch -ex "run" -ex "bt" ${my_program} 2>&1 | grep -v ^"No stack."$
Мне интересно, можно ли запускать приложение через GDB, в SegFault записывать обратную трассировку в файл (смотреть позже), а затем выходить из GDB без ввода какого-либо пользователя.
Я запускаю приложение из оболочки script в бесконечном цикле (так что если он сбрасывает его перезагрузку) при загрузке ОС из неинтерактивного сеанса. Приложение рушится невоспроизводимым образом, поэтому мне нужна обратная трасса от аварии, чтобы отладить проблему. В идеале я бы просто изменил оболочку script, включив функцию отладки GDB + backtracing и сохранил автоматический перезапуск приложения после сбоя.
Можно ли это сделать?
Благодаря Адитья Кумару; приемлемое решение:
gdb -batch -ex "run" -ex "bt" ${my_program} 2>&1 | grep -v ^"No stack."$
Это работает с gdb 7.6:
Моя тестовая программа, которая вызывает дамп ядра, если ему задан параметр командной строки:
int a(int argc)
{
if (argc > 1) {
int *p = 0;
*p = *p +1;
return *p;
}
else {
return 0;
}
}
int b(int argc)
{
return a(argc);
}
int main(int argc, char *argv[])
{
int res = b(argc);
return res;
}
Мой python script my_check.py:
def my_signal_handler (event):
if (isinstance(event, gdb.SignalEvent)):
log_file_name = "a.out.crash." + str(gdb.selected_inferior().pid) + ".log"
gdb.execute("set logging file " + log_file_name )
gdb.execute("set logging on")
gdb.execute("set logging redirect on")
gdb.execute("thread apply all bt")
gdb.execute("q")
gdb.events.stop.connect(my_signal_handler)
gdb.execute("set confirm off")
gdb.execute("set pagination off")
gdb.execute("r")
gdb.execute("q")
Итак, сначала я запускаю a.out и нет сбоя. Файлы журнала не создаются:
gdb -q -x my_check.py --args./a.out > /dev/null
Далее я запустил a.out и дал ему один параметр:
>gdb -q -x my_check.py --args ./a.out 1 >/dev/null
И это отчет о сбоях:
>cat a.out.crash.13554.log
Thread 1 (process 13554):
#0 0x0000000000400555 in a (argc=2) at main.cpp:5
#1 0x000000000040058a in b (argc=2) at main.cpp:15
#2 0x00000000004005a3 in main (argc=2, argv=0x7fffffffe198) at main.cpp:20
В качестве альтернативы просто сохранить обратную трассировку, вы можете поставить ulimit -c unlimited
перед своим бесконечным циклом в своей оболочке script. Результат будет заключаться в том, что каждый раз, когда ваша программа segfaults, он будет писать дамп ядра в файл, который в моей системе просто называется core
, а на других системах может включать идентификатор процесса. Если программа segfaults (вы видите, что из ее статуса выхода равна 139), просто переместите файл core
в безопасное место с использованием уникального имени (например, используя временные метки). С этими основными файлами и gdb вы можете сделать еще больше, чем просто смотреть на обратную трассировку. Таким образом, я предполагаю, что использование их может даже оказаться более полезным для вас.