Stack-Traces automatisch auf Unix-Systemen abrufen


7

Welche Methoden gibt es, um auf Unix-Systemen automatisch einen Stack-Trace zu bekommen? Ich meine damit nicht nur eine Kerndatei oder eine Verknüpfung mit GDB, sondern einen SIGSEGV-Handler, der ein Backtrace in eine Textdatei schreibt.

Bonuspunkte für die folgenden optionalen Funktionen: (. ZB Konfigurationsdateien)

  • Zusätzliche Informationen zu Absturz Zeit zu sammeln.
  • E-Mail ein Crash-Info-Paket an die Entwickler.
  • Fähigkeit, dies in einer gemeinsamen dlopen ed hinzufügen Bibliothek
  • ohne eigene GUI-
7

Wenn Sie auf Systeme mit der BSD backtrace Funktionalität zur Verfügung (Linux, OSX 1.5 BSD natürlich) sind, können Sie programmiere das programmatisch in deinem Signal-Handler.

Zum Beispiel (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(); 
} 

Ausgang:

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 

Diese Bonuspunkte für die optionalen Funktionen (mit Ausnahme keine GUI erfordert), jedoch nicht bekommen, es hat der Vorteil, dass es sehr einfach ist und keine zusätzlichen Bibliotheken oder Programme benötigt.


2

Dereks Lösung ist wahrscheinlich die beste, aber hier ist eine Alternative sowieso:

Aktuelle Linux-Kernel-Version ermöglicht Rohrkern zu einem Skript oder Programm-Dumps. Sie könnten ein Skript schreiben, um den Core-Dump abzufangen, zusätzliche Informationen zu sammeln und alles zurückzuschicken. Dies ist jedoch eine globale Einstellung, so dass es für jedes Absturzprogramm auf dem System gelten würde. Es erfordert auch Root-Rechte einzurichten. Es kann über die Datei/proc/sys/kernel/core_pattern konfiguriert werden. Setze das auf etwas wie '|/home/myuser/bin/mein-core-handler-script '.

Die Benutzer von Ubuntu verwenden diese Funktion ebenfalls.


4

Hier ist ein Beispiel, wie man mehr Informationen mit einem Demaggler bekommt. Wie Sie sehen können, protokolliert dieser auch den StackTrace in Datei.

#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

mit C++ in Signalhandlern - Fehler im Genom. 05 jan. 102010-01-05 08:54:40


15

FYI,

die vorgeschlagene Lösung (backtrace_symbols in einem Signalbehandlungsroutine verwendet wird) ist gefährlich gebrochen. Verwenden Sie es nicht -

Ja, Backtrace und backtrace_symbols einen Backtrace erzeugen und es zu symbolischen Namen übersetzen, aber:

  1. backtrace_symbols reserviert Speicher malloc und Sie frei, um es zu befreien - Wenn Sie Aufgrund von Speicherbeschädigung ist Ihre Malloc-Arena sehr wahrscheinlich korrupt und verursacht einen doppelten Fehler.

  2. malloc und kostenlos schützen die Malloc Arena mit einem Schloss intern.Sie könnten in der Mitte eines malloc/free mit der Sperre belegt sein, die diese Funktion oder irgendetwas verursacht, das sie zum totalen Sperren aufruft.

  3. Sie verwenden Puts, die den Standardstream verwenden, der ebenfalls durch eine Sperre geschützt ist. Wenn Sie mitten in einem Printf einen Fehler gemacht haben, haben Sie wieder einen Deadlock.

  4. Auf 32bit-Plattformen (zB Ihr normaler PC von vor 2 Jahren), wird der Kernel eine Rücksprungadresse auf eine interne Glibc-Funktion anstelle Ihrer fehlerhaften Funktion in Ihrem Stapel pflanzen, also die wichtigste Information Interesse an - in welcher Funktion der Programmfehler aufgetreten ist, wird auf diesen Plattformen tatsächlich verfälscht.

der Code in dem Beispiel also ist die schlimmste Art von falsch - es sieht aus wie es funktioniert, aber es wird Ihnen wirklich nicht auf unerwartete Weise in der Produktion.

BTW, Interesse daran, es richtig zu machen? Überprüfen Sie this aus.

Prost, Gilad.

+3

Bereitgestellte Verbindung ist tot. 27 mai. 102010-05-27 13:23:39

  0

Ich bin nicht sehr in der Gegend bewandert. Aber wenn du das Backtracing im Child-Prozess ausgibst und ausführst, kannst du davonkommen, oder? 26 feb. 182018-02-26 21:40:10