Получение следов стека в системах Unix, автоматически


7

Какие существуют методы автоматического получения трассировки стека в системах Unix? Я не имею в виду просто получение основного файла или интерактивное подключение к GDB, но с обработчиком SIGSEGV, который выгружает обратную трассировку в текстовый файл.

Бонусные баллы за следующие дополнительные функции: (например. Конфигурационные файлы)

  • Дополнительная информация сбора во время аварии.
  • Отправьте электронное сообщение с кратким сообщением разработчикам.
  • Возможность добавить это в dlopen эд общей библиотеки в
  • Не требует GUI
7

Если вы на системах с функциональностью BSD backtrace доступной (Linux, OSX 1,5, BSD, конечно), вы можете сделайте это программно в своем обработчике сигналов.

Например (backtrace code derived from IBM example):

#include <execinfo.h> 
#include <signal.h> 
#include <stdio.h> 
#include <stdlib.h> 

void sig_handler(int sig) 
{ 
    void * array[25]; 
    int nSize = backtrace(array, 25); 
    char ** symbols = backtrace_symbols(array, nSize); 

    for (int i = 0; i < nSize; i++) 
    { 
     puts(symbols[i]);; 
    } 

    free(symbols); 

    signal(sig, &sig_handler); 
} 

void h() 
{ 
    kill(0, SIGSEGV); 
} 

void g() 
{ 
    h(); 
} 

void f() 
{ 
    g(); 
} 

int main(int argc, char ** argv) 
{ 
    signal(SIGSEGV, &sig_handler); 
    f(); 
} 

Выход:

0 a.out        0x00001f2d sig_handler + 35 
1 libSystem.B.dylib     0x95f8f09b _sigtramp + 43 
2 ???         0xffffffff 0x0 + 4294967295 
3 a.out        0x00001fb1 h + 26 
4 a.out        0x00001fbe g + 11 
5 a.out        0x00001fcb f + 11 
6 a.out        0x00001ff5 main + 40 
7 a.out        0x00001ede start + 54 

Это не получает бонусные очки для дополнительных функций (за исключением не требующих GUI), однако, у него есть преимущество очень простое и не требует дополнительных библиотек или программ.


2

решение Dereks, вероятно, лучше, но вот альтернатива так или иначе:

Последние версии ядра Linux позволяют вам основной трубы свалки для сценария или программы. Вы можете написать скрипт, чтобы поймать основной дамп, собрать всю необходимую информацию и отправить все обратно. Это глобальная настройка, поэтому она применима к любой сбоя программы в системе. Это также потребует прав root для настройки. Его можно настроить через файл/proc/sys/kernel/core_pattern. Установите это как-то вроде '|/Главная/MyUser/бен/мой-ядро-обработчик-скрипт.

Люди Ubuntu также используют эту функцию.


4

Вот пример того, как получить дополнительную информацию с помощью демангера. Как вы можете видеть, этот файл также записывает файл stacktrace в файл.

#include <iostream> 
#include <sstream> 
#include <string> 
#include <fstream> 
#include <cxxabi.h> 

void sig_handler(int sig) 
{ 
    std::stringstream stream; 
    void * array[25]; 
    int nSize = backtrace(array, 25); 
    char ** symbols = backtrace_symbols(array, nSize); 
    for (unsigned int i = 0; i < size; i++) { 
     int status; 
     char *realname; 
     std::string current = symbols[i]; 
     size_t start = current.find("("); 
     size_t end = current.find("+"); 
     realname = NULL; 
     if (start != std::string::npos && end != std::string::npos) { 
      std::string symbol = current.substr(start+1, end-start-1); 
      realname = abi::__cxa_demangle(symbol.c_str(), 0, 0, &status); 
     } 
     if (realname != NULL) 
      stream << realname << std::endl; 
     else 
      stream << symbols[i] << std::endl; 
     free(realname); 
    } 
    free(symbols); 
    std::cerr << stream.str(); 
    std::ofstream file("/tmp/error.log"); 
    if (file.is_open()) { 
     if (file.good()) 
      file << stream.str(); 
     file.close(); 
    } 
    signal(sig, &sig_handler); 
} 
+1

Использование C++ в обработчиках сигналов - ошибка в геноме. 05 янв. 102010-01-05 08:54:40


15

FYI,

предложенное решение (с использованием backtrace_symbols в обработчике сигнала) опасно нарушена. НЕ ИСПОЛЬЗОВАТЬ -

Да, трассировку и backtrace_symbols будет производить трассировку и перевести его на символические имена, однако:

  1. backtrace_symbols выделяет память с помощью таНос и использовать бесплатно, чтобы освободить его, - если вы «Сбой из-за повреждения памяти ваша арена malloc, скорее всего, будет повреждена и вызовет двойную ошибку.

  2. malloc и свободно защищать арену malloc с замком внутри.Возможно, вы столкнулись с ошибкой в ​​середине malloc/free с помощью блокировки, которая вызовет эту функцию или что-нибудь, что называет их мертвой блокировкой.

  3. Вы используете puts, который использует стандартный поток, который также защищен блокировкой. Если вы ошибались в середине printf, у вас снова есть тупик.

  4. На 32-битных платформах (например, ваш обычный ПК 2 года назад) ядро ​​будет устанавливать обратный адрес во внутреннюю функцию glibc вместо вашей функции сбоя в вашем стеке, поэтому самая важная часть информации, которую вы используете заинтересованный - в какой функции произошла ошибка программы, на самом деле будет повреждена на этой платформе.

Таким образом, код в примере это худший вид неправильно - это выглядит, как это работает, но это будет действительно подведет вас неожиданным образом в производстве.

КБТО, заинтересован в этом? проверьте this вне.

Cheers, Gilad.

+3

При условии, что ссылка мертва. 27 май. 102010-05-27 13:23:39

  0

Я не ужасно разбираюсь в этом районе. Но если вы разворачиваете и выполняете обратную трассировку в дочернем процессе, вы можете уйти, нет? 26 фев. 182018-02-26 21:40:10