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

Qt GUI Recover from a SIGSEGV



  • I want to be able to recover from a Segmentation Fault in MyApplication by catching the SIGSEGV and restarting QApplication. So for testing purposes I'm injecting a segmentation fault in my code.

    The issue is that the signal handler that catches the SIGSEGV is getting a non-stop stream of SIGSEGVs. At first I thought it was the while loop in my main but it still happens even though I comment out the while loop. So my questions are simple: Is it even possible to recover from a Segmentation Fault in Qt? Why am I getting rolling SIGSEGVs non-stop?

    #include <QApplication>
    #include <QDebug>
    #include "MyApplication.h"
    
    #include <initializer_list>
    #include <signal.h>
    #include <unistd.h>
    #include <stdio.h>
    
    #define RESTART_CODE 1000
    
    void catchUnixSignals(std::initializer_list<int> quitSignals)
    {
        auto handler = [](int sig) -> void
        {
            if (sig == SIGSEGV)
            {
                QCoreApplication::exit(RESTART_CODE);
            }
            else
            {
                QCoreApplication::quit();
            }
        };
    
        sigset_t blocking_mask;
        sigemptyset(&blocking_mask);
        for (auto sig : quitSignals)
            sigaddset(&blocking_mask, sig);
    
        struct sigaction sa;
        sa.sa_handler = handler;
        sa.sa_mask    = blocking_mask;
        sa.sa_flags   = 0;
    
        for (auto sig : quitSignals)
            sigaction(sig, &sa, nullptr);
    }
    
    int main(int argc, char *argv[])
    {
        catchUnixSignals({SIGSEGV, SIGQUIT, SIGINT, SIGTERM, SIGHUP, SIGKILL});
    
        int i = 0;
        do
        {
            QApplication app(argc, argv);
    
            MyApp myapp;
            MyApp.start();
    
            app.exec();
    
            if (app.exec() != RESTART_CODE) break;
        } while(1);
    
        return 0;
    }
    


  • @anshah
    Why are trying to do such a thing in the first place? Catching and continuing safely after, say, SIGSEGV is fraught at best.

    You may want to Google for trap sigsegv and read through the various articles (e.g. stackoverflow) where people discuss this.

    Meanwhile: I'm not sure for the exact reason of your continuing problem. However, if you do trap a signal you are only allowed to do very limited things indeed inside the handler. In yours you choose to call QCoreApplication::exit/quit(). These are likely to invoke complex code, and wouldn't surprise me at all if there are problems in what it calls.

    If you really want to try this, I would arrange (somehow) that the handler only does something very simple like setting a flag. And then exit the handler. Then have caller inspect the flag and have it call the QCoreApplication methods. But I agree this may be difficult to achieve, once you trap a signal when you exit the handler you are allowing code to continue from the point where it got the signal, and if it does that goodness knows what it will then try to do next.

    So again: why do you expect/want to try to trap such a signal?



  • In the signal handler you are only allowed to do really basic things (see here what you can do).
    So as JonB already pointed out QCoreApllication probably is not from that category.
    Besides not working it is also really dangerous to try such things because the program is at a state where is has undefined behavior so more or less anything could happen.

    Now the constructive part: What I would do is make a second application or script, that just loops around and checks if your application is still running and if not then starts it.



  • @anshah as suggested by @gde23 you may want to rely on some other application/script/service to watchdog for your Qt app and restart it just in case.

    You may want to look at this example using systemd


Log in to reply