Aufruf von Qt-Funktionen aus Unix-Signal-Handlern
Sie können keine Qt-Funktionen aus Unix-Signal-Handlern aufrufen. Es gilt die Standardregel von POSIX: Aus Signal-Handlern dürfen nur async-signal-safe-Funktionen aufgerufen werden. Eine vollständige Liste der Funktionen, die Sie aus Unix-Signal-Handlern aufrufen können, finden Sie unter „Signal-Aktionen “.
Aber keine Sorge, es gibt eine Möglichkeit, Unix-Signal-Handler mit Qt zu verwenden. Die Strategie besteht darin, dass Ihr Unix-Signal-Handler etwas ausführt, das letztendlich dazu führt, dass ein Qt-Signal ausgelöst wird, und dann kehren Sie einfach aus Ihrem Unix-Signal-Handler zurück. Zurück in Ihrem Qt-Programm wird dieses Qt-Signal ausgesendet und anschließend von Ihrer Qt-Slot-Funktion empfangen, wo Sie dann problemlos alle Qt-Funktionen ausführen können, die im Unix-Signal-Handler nicht zulässig waren.
Eine einfache Möglichkeit, dies zu erreichen, besteht darin, in Ihrer Klasse für jedes Unix-Signal, das Sie verarbeiten möchten, ein Socket-Paar zu deklarieren. Die Socket-Paare werden als statische Datenelemente deklariert. Außerdem erstellen Sie eine ` QSocketNotifier `, um das Leseende jedes Socket-Paares zu überwachen, deklarieren Ihre Unix-Signalhandler als statische Klassenmethoden und deklarieren für jeden Ihrer Unix-Signalhandler eine entsprechende Slot-Funktion. In diesem Beispiel wollen wir sowohl die Signale `SIGHUP` als auch `SIGTERM` verarbeiten. Hinweis: Sie sollten die Manpages zu `socketpair(2)` und `sigaction(2)` lesen, bevor Sie sich durch die folgenden Codeausschnitte arbeiten.
class MyDaemon : public QObject
{
Q_OBJECT
public:
MyDaemon(QObject *parent = 0);
~MyDaemon();
// Unix signal handlers.
static void hupSignalHandler(int unused);
static void termSignalHandler(int unused);
public slots:
// Qt signal handlers.
void handleSigHup();
void handleSigTerm();
private:
static int sighupFd[2];
static int sigtermFd[2];
QSocketNotifier *snHup;
QSocketNotifier *snTerm;
};Verwenden Sie im Konstruktor von `MyDaemon` die Funktion `socketpair(2)`, um jedes Dateideskriptorpaar zu initialisieren, und erstellen Sie anschließend den ` QSocketNotifier `, um die Lese-Seite jedes Paares zu überwachen. Das Signal `activated()` jedes ` QSocketNotifier ` wird mit der entsprechenden Slot-Funktion verknüpft, die das Unix-Signal effektiv in das Signal ` QSocketNotifier::activated()` umwandelt.
MyDaemon::MyDaemon(QObject*parent)
: QObject(parent)
{
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sighupFd))
qFatal("Couldn't create HUP socketpair");
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigtermFd))
qFatal("Couldn't create TERM socketpair");
snHup = new QSocketNotifier(sighupFd[1], QSocketNotifier::Read, this);
connect(snHup, &QSocketNotifier::activated, this, &MyDaemon::handleSigHup);
snTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, this);
connect(snTerm, &QSocketNotifier::activated, this, &MyDaemon::handleSigTerm);
...
}Initialisiere die statischen Mitglieder in der Implementierungsdatei:
int MyDaemon::sighupFd[2] = {0, 0};
int MyDaemon::sigtermFd[2] = {0, 0};An einer anderen Stelle in Ihrem Startcode installieren Sie Ihre Unix-Signal-Handler mit `sigaction(2)`.
static int setup_unix_signal_handlers()
{
struct sigaction hup, term;
hup.sa_handler = MyDaemon::hupSignalHandler;
sigemptyset(&hup.sa_mask);
hup.sa_flags = 0;
hup.sa_flags |= SA_RESTART;
if (sigaction(SIGHUP, &hup, 0))
return 1;
term.sa_handler = MyDaemon::termSignalHandler;
sigemptyset(&term.sa_mask);
term.sa_flags = 0;
term.sa_flags |= SA_RESTART;
if (sigaction(SIGTERM, &term, 0))
return 2;
return 0;
}In Ihren Unix-Signal-Handlern schreiben Sie ein Byte an das Schreibende eines Socket-Paares und kehren zurück. Dies bewirkt, dass der entsprechende „ QSocketNotifier “ sein „activated()“-Signal aussendet, was wiederum dazu führt, dass die entsprechende Qt-Slot-Funktion ausgeführt wird.
void MyDaemon::hupSignalHandler(int)
{
char a = 1;
::write(sighupFd[0], &a, sizeof(a));
}
void MyDaemon::termSignalHandler(int)
{
char a = 1;
::write(sigtermFd[0], &a, sizeof(a));
}In den Slot-Funktionen, die mit den Signalen „ QSocketNotifier::activated()“ verbunden sind, lesen Sie das Byte ein. Nun befinden Sie sich mit Ihrem Signal wieder sicher in Qt und können alle Qt-Funktionen ausführen, die Ihnen im Unix-Signal-Handler nicht erlaubt waren.
void MyDaemon::handleSigTerm()
{
snTerm->setEnabled(false);
char tmp;
::read(sigtermFd[1], &tmp, sizeof(tmp));
// do Qt stuff
snTerm->setEnabled(true);
}
void MyDaemon::handleSigHup()
{
snHup->setEnabled(false);
char tmp;
::read(sighupFd[1], &tmp, sizeof(tmp));
// do Qt stuff
snHup->setEnabled(true);
}© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.