Вызов функций Qt из обработчиков сигналов UnixВы не можете вызывать функции Qt из обработчиков сигналов Unix. Правило стандарта POSIX применяется: Вы можете вызывать только асинхронные сигналобезопасные (async-signal-safe) функции из обработчиков событий. Полный список функций, которые вы можете вызвать из обработчиков сигналов Unix, смотрите в Signal Actions. Но не отчаивайтесь, имеется способ использования обработчиков сигналов Unix вместе с Qt. Стратегия заключается в том, чтобы заставить делать ваш обработчик сигналов что-либо, что приведёт в конечном счёте к отправке сигнала Qt, а затем вы просто вернёте управление из обработчика сигналов Unix. Потом в вашей программе Qt, отправляющая сигнал Qt, который затем получит ваша слот-функция Qt, где можно безопасно сделать что-нибудь присущее Qt, что нельзя сделать в обработчике сигналов Unix. Один из простых способов сделать это - объявить пару сокетов в вашем классе для каждого сигнала Unix, который вы хотите обрабатывать. Пары сокетов объявляются как статические члены данных. Также можно создать QSocketNotifier для наблюдения за читающим концом пары сокетов, объявить обработчики событий Unix статическими методами класса и объявить слот-функцию, соответствующую каждому обработчику событий Unix. В данном примере мы планируем обрабатывать сигналы SIGHUP и SIGTERM. Замечание: Прочтите оперативные страницы руководства (man pages) socketpair(2) и sigaction(2) перед изучением следующих фрагментов кода. 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; }; В конструкторе MyDaemon используем функцию socketpair(2) для инициализации каждой пары дескрипторов файлов, а затем создаем QSocketNotifier для наблюдения за читающим концом каждой пары. Сигнал activated() каждого QSocketNotifier соединён с соответствующей слот-функцией, которая по существу преобразует сигнал Unix в сигнал 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 = new QSocketNotifier(sighupFd[1], QSocketNotifier::Read, this); connect(snHup, SIGNAL(activated(int)), this, SLOT(handleSigHup())); snTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, this); connect(snTerm, SIGNAL(activated(int)), this, SLOT(handleSigTerm())); ... } Где-либо в другом месте в коде инициализации установите свои обработчики сигналов Unix с помощью 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) > 0) return 1; term.sa_handler = MyDaemon::termSignalHandler; sigemptyset(&term.sa_mask); term.sa_flags |= SA_RESTART; if (sigaction(SIGTERM, &term, 0) > 0) return 2; return 0; } В обработчиках сигналов Unix записываем байт в записывающий конец пары сокетов и возвращаем управление. Это приведёт к отправке соответствующим QSocketNotifier сигнала activated(), который будет по очереди запускать соответствующую слот-функцию 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)); } В слот-функциях, соединённых с сигналами QSocketNotifier::activated(), прочитаем байт. Теперь можно вернуться к Qt с сигналом и делать все присущее Qt, чего не получалось сделать в обработчике сигналов Unix. void MyDaemon::handleSigTerm() { snTerm->setEnabled(false); char tmp; ::read(sigtermFd[1], &tmp, sizeof(tmp)); // делаем что-то, присущее Qt snTerm->setEnabled(true); } void MyDaemon::handleSigHup() { snHup->setEnabled(false); char tmp; ::read(sighupFd[1], &tmp, sizeof(tmp)); // делаем что-то, присущее Qt snHup->setEnabled(true); } |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |