Appel de fonctions Qt à partir de gestionnaires de signaux Unix
Vous ne pouvez pas appeler de fonctions Qt à partir de gestionnaires de signaux Unix. La règle POSIX standard s'applique : Vous ne pouvez appeler que des fonctions asynchrones sûres pour les signaux à partir de gestionnaires de signaux. Voir Actions de signal pour la liste complète des fonctions que vous pouvez appeler à partir de gestionnaires de signaux Unix.
Mais ne désespérez pas, il existe un moyen d'utiliser les gestionnaires de signaux Unix avec Qt. La stratégie consiste à faire en sorte que votre gestionnaire de signaux Unix fasse quelque chose qui provoquera éventuellement l'émission d'un signal Qt, puis à revenir simplement de votre gestionnaire de signaux Unix. De retour dans votre programme Qt, ce signal Qt est émis puis reçu par votre fonction Qt slot, où vous pouvez faire en toute sécurité tout ce que vous n'étiez pas autorisé à faire dans le gestionnaire de signal Unix.
Une façon simple d'y parvenir est de déclarer une paire de sockets dans votre classe pour chaque signal Unix que vous souhaitez gérer. Les paires de sockets sont déclarées comme des membres de données statiques. Vous créez également un site QSocketNotifier pour surveiller la lecture de chaque paire de sockets, déclarez que vos gestionnaires de signaux Unix sont des méthodes de classe statiques et déclarez une fonction slot correspondant à chacun de vos gestionnaires de signaux Unix. Dans cet exemple, nous avons l'intention de gérer les signaux SIGHUP et SIGTERM. Note : Nous vous conseillons de lire les pages de manuel socketpair(2) et sigaction(2) avant de vous plonger dans les extraits de code suivants.
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; };
Dans le constructeur de MyDaemon, utilisez la fonction socketpair(2) pour initialiser chaque paire de descripteurs de fichiers, puis créez QSocketNotifier pour surveiller la fin de lecture de chaque paire. Le signal activated() de chaque QSocketNotifier est connecté à la fonction slot appropriée, qui convertit effectivement le signal Unix en signal QSocketNotifier::activated().
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 = nouveau 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) ; .. .}
Initialiser les membres statiques dans le fichier d'implémentation :
int MyDaemon::sighupFd[2] = {0, 0}; int MyDaemon::sigtermFd[2] = {0, 0};
A un autre endroit de votre code de démarrage, vous installez vos gestionnaires de signaux Unix avec 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; }
Dans vos gestionnaires de signaux Unix, vous écrivez un octet à l'extrémité d'écriture d' une paire de sockets et vous retournez. QSocketNotifier Ceci provoquera l'émission du signal activated() par l'Active Qt correspondant, qui à son tour provoquera l'exécution de la fonction slot appropriée de Qt.
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)); }
Dans les fonctions slot connectées aux signaux QSocketNotifier::activated(), vous lisez l 'octet. Maintenant, vous êtes de retour en toute sécurité dans Qt avec votre signal, et vous pouvez faire toutes les choses de Qt que vous n'étiez pas autorisé à faire dans le gestionnaire de signal Unix.
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.