[Interest] Creating a debug log with a stacktrace on Linux

Rogers Nate nate.rogers at raymondcorp.com
Thu Jun 26 16:05:35 CEST 2014


I am trying to capture some debug information to eventually add to a log in my application but my stacktrace doesn't contain the actual names of the functions that are being call (at least that I can see).  How can I get a stack trace that is more meaningful or easier to read?

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
-------------------------------------------------------------------------------------------------------


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(QFlags<QEventLoop::ProcessEventsFlag>) + 0xc3
  /home/nrogers/Qt5.2.0/5.2.0/gcc_64/lib/libQt5Core.so.5  :  QEventLoop::exec(QFlags<QEventLoop::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


Confidentiality Notice: The preceding e-mail message (including any attachments) contains information that may be confidential, protected by applicable legal privileges, or constitute non-public information. It is intended to be conveyed only to the designated recipient(s). If you are not an intended recipient of this message, please notify the sender by replying to this message and then delete it from your system. Use, dissemination, distribution or reproduction of this message by unintended recipients is not authorized and may be unlawful.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20140626/eaa6996e/attachment.html>


More information about the Interest mailing list