Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QApplication: How to shutdown gracefully on Ctrl-C

Tags:

c++

unix

qt

I have a QApplication that, depending on command line parameters, sometimes doesn't actually have a GUI window, but just runs without GUI. In this case, I want to shut it down gracefully if CTRL-C was hit. Basically my code looks like this:

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

    ... // parse command line options

    if (no_gui) {
        QObject::connect(&app, SIGNAL(unixSignal(int)),
                         &app, SLOT(quit()));
        app.watchUnixSignal(SIGINT, true);
        app.watchUnixSignal(SIGTERM, true);
    }

    ... 

    return app.exec();
}

However, this does not work. CTRL-C seems to be caught (the application doesn't get killed), but it also doesn't exit. What am I missing?

like image 625
Martin Avatar asked Feb 19 '10 23:02

Martin


3 Answers

There may be a way to do this natively with Qt -- I poked around the QKeySequence docs for a bit before giving up, but you can just use signal. I don't have Qt/C++ setup on my machine at the moment, but I do have the Python bindings.

import sys, signal
from PyQt4 import QtGui

app = QtGui.QApplication(sys.argv)
signal.signal(signal.SIGINT, signal.SIG_DFL)

sys.exit(app.exec_())

This works and will close the application when I do Ctrl-C. So I believe that your application could adapt this code and it would end up something like this:

#include <signal.h>

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

    ... // parse command line options

    if (no_gui) {
        signal(SIGINT, SIG_DFL);
    }

    ... 

    return app.exec();
}

Unfortunately, I cannot compile this so it will probably need a few fixes, but this should give you the general idea. By using the SIG_DFL handler you are instructing your program to use the default action associated with Ctrl-C.

like image 150
swanson Avatar answered Oct 24 '22 08:10

swanson


As it isn't documented, QApplication::watchUnixSignal shouldn't be used. And, from reading the code, it will not work properly when using the glib event dispatcher (which is the default on Linux).

However, in general you can safely catch Unix signals in Qt applications, you just have to write a bit of the code yourself. There is even an example in the documentation - Calling Qt Functions From Unix Signal Handlers.

like image 36
rohanpm Avatar answered Oct 24 '22 08:10

rohanpm


You can use QApplication::instance() (or the shorter macro version qApp), both available since at least Qt4:

#include <QApplication>
#include <csignal>

void sigHandler(int s)
{
    std::signal(s, SIG_DFL);
    qApp->quit();
}

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

    std::signal(SIGINT,  sigHandler);
    std::signal(SIGTERM, sigHandler);

    return app.exec();
}
like image 6
Chnossos Avatar answered Oct 24 '22 08:10

Chnossos