我想知道如何在关闭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
?我认为它有一个信号。
答案 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
功能,而是在其析构函数中正确管理其资源。如果你愿意,你可以把它变成单身。