QApplication: как корректно завершить работу на Ctrl-C - PullRequest
22 голосов
/ 20 февраля 2010

У меня есть приложение QApplication, которое, в зависимости от параметров командной строки, иногда не имеет окна с графическим интерфейсом, а просто работает без графического интерфейса. В этом случае я хочу отключить его корректно, если была нажата CTRL-C. В основном мой код выглядит так:

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();
}

Однако это не работает. CTRL-C, кажется, перехвачен (приложение не убивается), но также не завершается. Чего мне не хватает?

Ответы [ 4 ]

19 голосов
/ 20 февраля 2010

Может быть способ сделать это изначально с Qt - я немного покопался в документации по QKeySequence, прежде чем сдаться, но вы можете просто использовать signal. В данный момент на моей машине не установлена ​​программа Qt / C ++, но у меня есть привязки Python.

import sys, signal
from PyQt4 import QtGui

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

sys.exit(app.exec_())

Это работает и закроет приложение, когда я сделаю Ctrl-C. Поэтому я считаю, что ваше приложение может адаптировать этот код, и в итоге это будет выглядеть примерно так:

#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();
}

К сожалению, я не могу скомпилировать это, поэтому, возможно, потребуется несколько исправлений, но это должно дать вам общее представление. Используя обработчик SIG_DFL, вы указываете своей программе использовать действие по умолчанию, связанное с Ctrl-C.

17 голосов
/ 20 февраля 2010

Поскольку это не задокументировано, QApplication::watchUnixSignal не должно использоваться. И, читая код, он не будет работать должным образом при использовании диспетчера событий glib (который по умолчанию в Linux).

Однако, как правило, вы можете безопасно перехватывать сигналы Unix в приложениях Qt, вам просто нужно написать немного кода самостоятельно. В документации есть даже пример - Вызов функций Qt из обработчиков сигналов Unix .

1 голос
/ 20 февраля 2010

Как упомянул Jerkface Jones, похоже, что он не работает с использованием обработчика событий по умолчанию в Linux.

Если Qt использует необработанный обработчик событий Unix (не-glib), Qt сразу же поймает и поглощает ^ C в своем обработчике сигналов, но сигнал unixSignal (int) не будет излучаться, пока Qt не выполнит обработку событий .

Если у вас работает код (а не бездельничает в ожидании, когда Qt отправит сигналы), вам нужно вызвать QApplication :: processEvents () , чтобы Qt отправил сигнал.

1 голос
/ 20 февраля 2010

Я не нашел больше информации о QApplication::watchUnixSignal документации, за исключением одного вкладыша для Qt 4.0; особенно это не задокументировано в более поздних версиях Qt. Таким образом, похоже, что эта функциональность не рекламируется (и поэтому не должна) работать. Делая это, "Qt way", очевидно, хорош, я бы просто воспользовался системным вызовом .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...