QApplication:如何在Ctrl-C上优雅地关闭。

时间:2023-02-11 04:00:58

I have a QApplication that, depending on command line parameters, sometimes doesn't actually has 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:

我有一个QApplication,它依赖于命令行参数,有时候实际上没有GUI窗口,但是只是运行没有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();
}

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?

然而,这并不奏效。CTRL-C似乎被捕获了(应用程序不会被杀死),但它也不会退出。我缺少什么?

4 个解决方案

#1


16  

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).

由于没有文档化,QApplication::不应该使用watchUnixSignal。而且,通过读取代码,当使用glib事件调度器(在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.

但是,一般来说,您可以安全地在Qt应用程序中捕获Unix信号,您只需自己编写一些代码。文档中甚至有一个例子——从Unix信号处理程序中调用Qt函数。

#2


17  

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.

可能有一种方法可以直接使用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_())

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:

当我执行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();
}

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.

不幸的是,我无法编译它,所以它可能需要一些修复,但这应该会给您一个大致的概念。通过使用SIG_DFL处理程序,您将指示您的程序使用与Ctrl-C相关联的默认操作。

#3


1  

I haven't found much more about QApplication::watchUnixSignal documentation except for a one liner for Qt 4.0; especially it's not documented in later versions of Qt. Thus it looks like this functionality isn't advertised (and therefore supposed) to work. While doing it the "Qt way" is obviously nice I'd simply fall back to using the signal system call instead.

我还没有找到更多关于QApplication::watchUnixSignal文档,除了qt4.0的一个行;特别是它在Qt的后续版本中没有被记录,因此看起来这个功能并没有广告(因此也应该是)工作。在做它的时候,“Qt方法”显然很好,我只是简单地使用了信号系统调用。

#4


1  

As Jerkface Jones mentioned, this looks like it doesn't work using the default event handler on Linux.

正如Jerkface Jones提到的那样,在Linux上使用默认的事件处理程序是行不通的。

If Qt is using the raw Unix (non-glib) event handler, Qt will catch and absorb the ^C right away in its signal handler, but the unixSignal(int) signal won't be emitted until Qt does event processing.

如果使用Qt原始Unix(non-glib)事件处理程序,Qt马上捕获和吸收^ C信号处理器,但unixSignal(int)信号不会被释放,直到Qt事件处理。

If you have code running (rather than idling around waiting for Qt to send signals), then you'll need to call QApplication::processEvents() for Qt to send the signal.

如果您有代码运行(而不是在等待Qt发送信号),那么您需要调用QApplication::processEvents()用于Qt发送信号。

#1


16  

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).

由于没有文档化,QApplication::不应该使用watchUnixSignal。而且,通过读取代码,当使用glib事件调度器(在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.

但是,一般来说,您可以安全地在Qt应用程序中捕获Unix信号,您只需自己编写一些代码。文档中甚至有一个例子——从Unix信号处理程序中调用Qt函数。

#2


17  

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.

可能有一种方法可以直接使用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_())

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:

当我执行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();
}

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.

不幸的是,我无法编译它,所以它可能需要一些修复,但这应该会给您一个大致的概念。通过使用SIG_DFL处理程序,您将指示您的程序使用与Ctrl-C相关联的默认操作。

#3


1  

I haven't found much more about QApplication::watchUnixSignal documentation except for a one liner for Qt 4.0; especially it's not documented in later versions of Qt. Thus it looks like this functionality isn't advertised (and therefore supposed) to work. While doing it the "Qt way" is obviously nice I'd simply fall back to using the signal system call instead.

我还没有找到更多关于QApplication::watchUnixSignal文档,除了qt4.0的一个行;特别是它在Qt的后续版本中没有被记录,因此看起来这个功能并没有广告(因此也应该是)工作。在做它的时候,“Qt方法”显然很好,我只是简单地使用了信号系统调用。

#4


1  

As Jerkface Jones mentioned, this looks like it doesn't work using the default event handler on Linux.

正如Jerkface Jones提到的那样,在Linux上使用默认的事件处理程序是行不通的。

If Qt is using the raw Unix (non-glib) event handler, Qt will catch and absorb the ^C right away in its signal handler, but the unixSignal(int) signal won't be emitted until Qt does event processing.

如果使用Qt原始Unix(non-glib)事件处理程序,Qt马上捕获和吸收^ C信号处理器,但unixSignal(int)信号不会被释放,直到Qt事件处理。

If you have code running (rather than idling around waiting for Qt to send signals), then you'll need to call QApplication::processEvents() for Qt to send the signal.

如果您有代码运行(而不是在等待Qt发送信号),那么您需要调用QApplication::processEvents()用于Qt发送信号。