Creating a debug log with a stacktrace on Linux



  • I am trying to capture some debug information to eventually add to a log with my application but my stacktrace doesn't contain any useful information (at least that I can decipher). Can someone give me some tips?

    main.cpp

    @#include "FiveWayDriver.h"

    const char* get_process_name_by_pid(const int pid)
    {
    char* name = (char*)calloc(1024,sizeof(char));
    if(name){
    sprintf(name, "/proc/%d/cmdline",pid);
    FILE* f = fopen(name,"r");
    if(f){
    size_t size;
    size = fread(name, sizeof(char), 1024, f);
    if(size>0){
    if('\n'==name[size-1])
    name[size-1]='\0';
    }
    fclose(f);
    }
    }
    return name;
    }

    /** Print a demangled stack backtrace of the caller function to FILE* out. */
    static inline void print_stacktrace()
    {
    unsigned int max_frames = 63;

    qDebug() << "stack trace:";
    
    // storage array for stack trace address data
    void* addrlist[max_frames+1];
    
    // retrieve current stack addresses
    int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));
    
    if (addrlen == 0)
    {
        qDebug() << "  <empty, possibly corrupt>";
        return;
    }
    
    // resolve addresses into strings containing "filename(function+address)", this array must be free()-ed
    char** symbollist = backtrace_symbols(addrlist, addrlen);
    
    // allocate string which will be filled with the demangled function name
    size_t funcnamesize = 256;
    char* funcname = (char*)malloc(funcnamesize);
    
    // iterate over the returned symbol lines. skip the first, it is the address of this function.
    for (int i = 1; i < addrlen; i++)
    {
    char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
    
    for (char *p = symbollist[i]; *p; ++p)
    {
        if (*p == '(')
        begin_name = p;
        else if (*p == '+')
        begin_offset = p;
        else if (*p == ')' && begin_offset) {
        end_offset = p;
        break;
        }
    }
    
    if (begin_name && begin_offset && end_offset
        && begin_name < begin_offset)
    {
        *begin_name++ = '\0';
        *begin_offset++ = '\0';
        *end_offset = '\0';
    
        int status;
        char* ret = abi::__cxa_demangle(begin_name,
                        funcname, &funcnamesize, &status);
        if (status == 0)
        {
            funcname = ret; // use possibly realloc()-ed string
            qDebug() << " " << symbollist[i] << " : " << funcname << "+" << begin_offset;
        }
        else
        {
            // demangling failed. Output function name as a C function with
            // no arguments.
            qDebug() << " " << symbollist[i] << " : " << begin_name << "+" << begin_offset;
        }
    }
    else
    {
        // couldn't parse the line? print the whole line.
        qDebug() << " " << symbollist[i];
    }
    }
    
    free(funcname);
    free(symbollist);
    

    }

    void sighandler(int signum)
    {
    qDebug() << "Process" << get_process_name_by_pid(getpid()) << " got signal " << signum;
    print_stacktrace();
    signal(signum, SIG_DFL);
    kill(getpid(), signum);
    }

    int main(int argc, char *argv[])
    {
    QCoreApplication app(argc, argv);

    // Create the five-way driver
    FiveWayDriver fiveWayDriver;
    
    // install our handler
    signal(SIGSEGV, sighandler);
    signal(SIGTERM, sighandler);
    
    return app.exec();
    

    }
    @

    FiveWayDriver.cpp

    @#include "FiveWayDriver.h"

    FiveWayDriver::FiveWayDriver()
    {
    // Setup the timer
    m_Timer = new QTimer(this);
    connect(m_Timer, SIGNAL(timeout()), this, SLOT(processFiveWayButton()));
    m_Timer->start(1000);
    }

    void FiveWayDriver::upButtonClicked()
    {
    int foo = (int)-1; // make a bad pointer
    printf("%d\n", *foo); // causes segfault
    }

    void FiveWayDriver::processFiveWayButton()
    {
    upButtonClicked();
    }

    void FiveWayDriver::toggleTimer()
    {
    if (m_Timer->isActive())
    {
    m_Timer->stop();
    }
    else
    {
    m_Timer->start();
    }
    }@

    FiveWayDriver.h

    @#ifndef FIVEWAYDRIVER_H
    #define FIVEWAYDRIVER_H

    #include <QCoreApplication>

    #include <execinfo.h>
    #include <errno.h>
    #include <cxxabi.h>

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

    class FiveWayDriver : public QObject
    {
    Q_OBJECT

    public:
    FiveWayDriver();

    public slots:
    void processFiveWayButton();

    private slots:
    void upButtonClicked();
    void toggleTimer();

    private:
    QTimer *m_Timer;
    };

    #endif // FIVEWAYDRIVER_H@

    To be continued...



  • [ontinued from above]

    What I am expecting to see it the QTimer calling processFiveWayButton() and that function calling upButtonClicked() but this is what actually comes out of the backtrace print...

    @
    Process /home/nrogers/dev/projects/DbusBreadboardDesktopBuild/Debug/FiveWayDriver/FiveWayDriver got signal 11
    stack trace:
    /home/nrogers/dev/projects/DbusBreadboardDesktopBuild/Debug/FiveWayDriver/FiveWayDriver() [0x40303e]
    /lib/x86_64-linux-gnu/libc.so.6 : + 0x364a0
    /home/nrogers/dev/projects/DbusBreadboardDesktopBuild/Debug/FiveWayDriver/FiveWayDriver() [0x403933]
    /home/nrogers/dev/projects/DbusBreadboardDesktopBuild/Debug/FiveWayDriver/FiveWayDriver() [0x403a18]
    /home/nrogers/dev/projects/DbusBreadboardDesktopBuild/Debug/FiveWayDriver/FiveWayDriver() [0x404e19]
    /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5 : QMetaObject::activate(QObject*, int, int, void**) + 0x2d1
    /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5 : QTimer::timerEvent(QTimerEvent*) + 0x32
    /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5 : QObject::event(QEvent*) + 0x69
    /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5 : QCoreApplication::notify(QObject*, QEvent*) + 0x3d
    /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5 : QCoreApplication::notifyInternal(QObject*, QEvent*) + 0x84
    /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5 : QTimerInfoList::activateTimers() + 0x50c
    /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5 : + 0x2d47ed
    /lib/x86_64-linux-gnu/libglib-2.0.so.0 : g_main_context_dispatch + 0x133
    /lib/x86_64-linux-gnu/libglib-2.0.so.0 : + 0x48060
    /lib/x86_64-linux-gnu/libglib-2.0.so.0 : g_main_context_iteration + 0x34
    /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5 : QEventDispatcherGlib::processEvents(QFlagsQEventLoop::ProcessEventsFlag) + 0xc3
    /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5 : QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag) + 0xcb
    /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5 : QCoreApplication::exec() + 0x7e
    /home/nrogers/dev/projects/DbusBreadboardDesktopBuild/Debug/FiveWayDriver/FiveWayDriver() [0x4030db]
    /lib/x86_64-linux-gnu/libc.so.6 : __libc_start_main + 0xed
    /home/nrogers/dev/projects/DbusBreadboardDesktopBuild/Debug/FiveWayDriver/FiveWayDriver() [0x4028f9]
    @

    Is there a way to get what I want (ie. QTimer calling processFiveWayButton() and that function calling upButtonClicked())? Thanks!

    Nate


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.