Подтвердить что ты не робот

QApplication: как закончить изложение на Ctrl-C

У меня есть QApplication, который, в зависимости от параметров командной строки, иногда на самом деле не имеет окна графического интерфейса, а просто работает без GUI. В этом случае я хочу закрыть его изящно, если 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 кажется пойманным (приложение не убивается), но оно также не выходит. Что мне не хватает?

4b9b3361

Ответ 1

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

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

Ответ 2

Возможно, есть способ сделать это изначально с помощью Qt - я немного поиграл с документами QKeySequence, прежде чем сдаваться, но вы можете просто использовать signal. На данный момент у меня нет настройки Qt/С++ на моей машине, но у меня есть привязки 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.

Ответ 3

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

Ответ 4

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

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

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