关闭控制台时C ++ / Qt运行功能

时间:2015-09-12 14:06:05

标签: c++ qt

我想知道如何在关闭Qt控制台应用程序的终端(我在Linux上)时运行一个函数。我有一个'静态'类,它包含我需要的所有变量(我知道我可以使用单例但我更喜欢这种方式)并且它有一个名为destroy的函数,这将删除所有指针。)

所以这是'静态'类的.cpp:

#include "engine.h"

logging* engine::m_logging;
tcp_listener* engine::m_tcp_listener;

void engine::initialize()
{
    engine::m_logging = new logging();

    engine::m_logging->write_line("Initializing Fullmoon Messenger server...");

    engine::m_tcp_listener = new tcp_listener();
    engine::m_tcp_listener->start("127.0.0.1", 30000);
}

void engine::destroy()
{
    delete engine::m_logging;
}

logging* engine::get_logging()
{
    return engine::m_logging;
}

这是我的main.cpp:

#include <QCoreApplication>

#include "engine.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    engine::initialize();

    return a.exec();
}

关闭应用程序时如何调用engine::destroy?我认为它有一个信号。

2 个答案:

答案 0 :(得分:4)

您需要为此处理POSIX信号SIGHUP

(注意:POSIX信号与Qt信号完全不同,因此它们不会被“插槽”处理。不要混淆它们。)

请注意,您在POSIX信号处理程序中执行操作的选项非常有限。手册页signal(7)列出了可以安全调用的函数。在对这个答案的评论中,Kuba Ober指出你应该坚持handling POSIX signals in Qt applications的官方文档。但由于文档中解释的过程非常复杂,我将其包装在可重用的类PosixSignalProxy中,将POSIX信号转换为Qt信号。

如果您使用此代理类,则只需编写:

PosixSignalProxy<SIGHUP> sighupProxy;
QObject::connect(&sighupProxy, &PosixSignalProxyBase::receivedSignal, []{
    engine::destroy();
});

该课程位于本文的底部。

请注意,每个POSIX信号类型只能创建一个PosixSignalProxy实例。如果在接收信号时需要做多件事,可以多次连接到Qt信号。

此外,您可能会因为退出应用程序的外部原因而对类似信号感兴趣,例如在终端窗口中将其删除或按Ctrl + C.

  • SIGHUP(如上例所示):当终端窗口关闭时(父进程被销毁)
  • SIGINT:当用户按Ctrl + C时 - 请注意,当您处理此信号时,您需要在处理程序的末尾退出,因为您的进程负责最终退出。您可以覆盖此默认行为,并且不仅可以清除内容,还可以忽略用户退出应用程序的愿望。
  • SIGTERM:当程序被杀死时,例如kill(不要与SIGKILL混淆,这是一种更具攻击性的方法来杀死进程;你无法处理那个进程)

这是类定义:

<强> posixsignalproxy.h

#ifndef POSIXSIGNALPROXY_H
#define POSIXSIGNALPROXY_H

#include <QObject>

class QSocketNotifier;

typedef void (*PosixSignalHandlerType) (int);

// Helper base class (no template) - Do not use this class directly.
class PosixSignalProxyBase : public QObject
{
    Q_OBJECT

public:
    PosixSignalProxyBase(
            QObject *parent,
            int (&sockets)[2],
            int posixSignalNumber,
            PosixSignalHandlerType posixSignalHandler,
            int posixSignalFlags);
    ~PosixSignalProxyBase();

signals:
    /**
     * Qt signal which is emitted right after receiving and handling the POSIX
     * signal. In the Qt signal handler (slot) you are allowed to do anything.
     */
    void receivedSignal();

protected:
    static void staticSignalHandler(int (&sockets)[2]);

private slots:
    void handleSignal();

private:
    int (&sockets)[2];
    QSocketNotifier *notifier;
};


// Actual proxy class, defining its own static proxy signal handler function and sockets.
template <int signum>
class PosixSignalProxy : public PosixSignalProxyBase
{
public:
    PosixSignalProxy(QObject *parent = nullptr, int posixSignalFlags = 0) :
        PosixSignalProxyBase(parent, mySockets, signum, &posixSignalHandler, posixSignalFlags)
    {}
    PosixSignalProxy(int posixSignalFlags) :
        PosixSignalProxy(nullptr, posixSignalFlags)
    {}

    static void posixSignalHandler(int) {
        PosixSignalProxyBase::staticSignalHandler(mySockets);
    }

private:
    static int mySockets[2];
};

template <int signum>
int PosixSignalProxy<signum>::mySockets[2];

#endif // POSIXSIGNALPROXY_H

<强> posixsignalproxy.cpp

#include "posixsignalproxy.h"

#include <QSocketNotifier>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>

PosixSignalProxyBase::PosixSignalProxyBase(QObject *parent, int (&sockets)[2], int posixSignalNumber, PosixSignalHandlerType posixSignalHandler, int posixSignalFlags) :
    QObject(parent),
    sockets(sockets)
{
    if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sockets))
       qFatal("PosixSignalProxy: Couldn't create socket pair");

    notifier = new QSocketNotifier(sockets[1], QSocketNotifier::Read, this);
    connect(notifier, SIGNAL(activated(int)), this, SLOT(handleSignal()));

    struct sigaction sa;

    sa.sa_handler = posixSignalHandler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = posixSignalFlags;

    if (sigaction(posixSignalNumber, &sa, 0) > 0)
        qFatal("PosixSignalProxy: Couldn't register POSIX signal handler");
}

PosixSignalProxyBase::~PosixSignalProxyBase()
{
    delete notifier;
}

void PosixSignalProxyBase::staticSignalHandler(int (&sockets)[2])
{
    char tmp = 1;
    ::write(sockets[0], &tmp, sizeof(tmp));
}


void PosixSignalProxyBase::handleSignal()
{
    notifier->setEnabled(false);
    char tmp;
    ::read(sockets[1], &tmp, sizeof(tmp));

    // Here, we're allowed to do Qt stuff.
    emit receivedSignal();

    notifier->setEnabled(true);
}

答案 1 :(得分:0)

如果你想使用信号,你正在寻找QCoreApplication::aboutToQuit

更好的想法IMO是engine不具备static功能,而是在其析构函数中正确管理其资源。如果你愿意,你可以把它变成单身。