Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Catching segfault



  • Hi,
    I want to provide an option to the user, to report App crash. The front end is in QML and from there C++ classes are being called.

    I installed a signal handler to catch SIGSEGV:
    ///main.cpp:

    void signal_handler(int signum) {
        signal(SIGSEGV, SIG_DFL);
        signal(SIGFPE, SIG_DFL);
        aewm_obj.show_fault(signum);
    }
    int main(int argc, char *argv[])
    {
       ....
        signal(SIGSEGV, signal_handler);
        signal(SIGFPE, signal_handler);
        ....
       QGuiApplication app(argc, argv);
       qml_engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
       ....
    }
    

    The show_fault function() should get the stack trace, and send signal to QML where the user will confirm sending of the crash report, something like this:

    void aewm::show_fault(int signum) {
        QString failure_description;
        failure_description=get_stack_trace();
        emit app_fault(signum,failure_description);
    }
    

    However this code seems to be producing another SEGFAULT which is a real SEGFAULT, not a test. Why is this happening? I am generating a test SEGFAULT with this code;

    void aewm::crash_app() {
        char *null_pointer=nullptr;
    
        *null_pointer='A';
    }
    

    The problem is, I can't even debug this with GDB since GDB has its own signal hander and it catches my test SIGSEGV.


  • Lifetime Qt Champion

    Hi,

    Do I understand correctly that you are trying to access your gui while your application is crashing ?



  • @SGaist

    yes, If a crash occurs (and I don't know where this is going to happen, within the GUI or, maybe Qt Network classes) I want to send the control to the QML where the user is going to confirm sending the crash report, and Exit the App after that.



  • @Nulik

    The problem is, I can't even debug this with GDB since GDB has its own signal hander and it catches my test SIGSEGV

    GDB allows you to catch/ignore/pass on signals as you choose. Can't you just continue, or perhaps handle SIGSEGV nostop?



  • @JonB said in Catching segfault:

    GDB allows you to catch/ignore/pass on signals as you choose. Can't you just continue, or perhaps handle SIGSEGV nostop?

    Thanks! Actually, my code works if I send SIGSEGV or SIGFPE from the console using kill -SEGV [PID] , but if I simulate a SIGSEGV by assigning some value to null pointer I can't recover from this.

    Is there a way to send control to QML's main event loop from the signal handler? Or how should one recover from SIGSEGV ? (i.e. abort current execution path and return back to main event loop)



  • or, maybe I should load another version "main.qml" containing only the Dialog with crash report and 'Send' button? (from the signal handler once it has received the SIGSEGV) I would need to initialize all the variables involved in this , because a SIGSEGV can corrupt memory. Any ideas on how to implement the 'crash report' feature will be greatly appreciated


  • Lifetime Qt Champion

    You have several examples given in the Wikipedia Crash reporter article.

    Breakpad comes to mind when going cross-platform. KDE's Dr Konqi might also be available on other platforms.



  • my problem is, that when signal handler exits, the code that caused the SIGSEGV is executed again, and again, in a loop. Hopefully I am clearing the signal handler inside the signal handler itself and it doesn't loop many times, but I that's why I am catching this SIGSEGV twice.



  • I have almost solved it, but for some reason QCoreApplication::exit() doesn't exits the main event loop and I cant reload a new main.qml file.

    Here is the description of the problem on StackOverflow: https://stackoverflow.com/questions/55699851/how-to-reload-main-qml-file



  • Once a segmentation fault has happened, you know you have a memory bug, and the whole process basically has to be assumed to be trashed. Accomplishing anything useful within it at that point is misguided. In general, you can only present the user with a crash handler by having a simple parent process monitoring the child process the user actually interacts with, and then the parent process can detect when the child process has died and present some sort of crash reporter UI if needed.


  • Moderators

    @wrosecrans said in Catching segfault:

    and the whole process basically has to be assumed to be trashed. Accomplishing anything useful within it at that point is misguided.

    I disagree. There are specific cases where you must handle the signal. Moreover you may have foreign code that generated the segfault (for example if you load plugins, and the user-programmer made an error), then it can be beneficial to respond to the signal appropriately and do a graceful shutdown, as much as this is possible.



  • @kshegunov Once the plugin has triggered a segfault, you know longer have any guarantee that anything in your address space is correct, so it's generally safest to just die rather than risk executing code that could do wildly incorrect things. Every bit that the signal handler uses to decide how to safely shut down is suspect at that point.


Log in to reply