Problems with Open-Source Downloads read https://www.qt.io/blog/problem-with-open-source-downloads and https://forum.qt.io/post/638946

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