Gdb backtrace без ввода пользователем?

Мне интересно, можно ли запускать приложение через GDB, в SegFault записывать обратную трассировку в файл (смотреть позже), а затем выходить из GDB без ввода какого-либо пользователя.

Я запускаю приложение из оболочки script в бесконечном цикле (так что если он сбрасывает его перезагрузку) при загрузке ОС из неинтерактивного сеанса. Приложение рушится невоспроизводимым образом, поэтому мне нужна обратная трасса от аварии, чтобы отладить проблему. В идеале я бы просто изменил оболочку script, включив функцию отладки GDB + backtracing и сохранил автоматический перезапуск приложения после сбоя.

Можно ли это сделать?

Ответы

Ответ 1

Благодаря Адитья Кумару; приемлемое решение:

gdb -batch -ex "run" -ex "bt" ${my_program} 2>&1 | grep -v ^"No stack."$

Ответ 2

Это работает с 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

Ответ 3

В качестве альтернативы просто сохранить обратную трассировку, вы можете поставить ulimit -c unlimited перед своим бесконечным циклом в своей оболочке script. Результат будет заключаться в том, что каждый раз, когда ваша программа segfaults, он будет писать дамп ядра в файл, который в моей системе просто называется core, а на других системах может включать идентификатор процесса. Если программа segfaults (вы видите, что из ее статуса выхода равна 139), просто переместите файл core в безопасное место с использованием уникального имени (например, используя временные метки). С этими основными файлами и gdb вы можете сделать еще больше, чем просто смотреть на обратную трассировку. Таким образом, я предполагаю, что использование их может даже оказаться более полезным для вас.