Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. How to get unix signals into Qt? (Embedded Linux)
Forum Updated to NodeBB v4.3 + New Features

How to get unix signals into Qt? (Embedded Linux)

Scheduled Pinned Locked Moved Mobile and Embedded
13 Posts 5 Posters 24.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    jsiei97
    wrote on 11 Oct 2010, 15:02 last edited by
    #1

    Hi

    Is there a way to get unix signals into the Qt world in a good way?

    I tried to follow this example but it's not working for me.

    • "http://developer.qt.nokia.com/faq/answer/is_there_a_qt_way_to_handle_unix_posix_signals":http://developer.qt.nokia.com/faq/answer/is_there_a_qt_way_to_handle_unix_posix_signals

    • "http://doc.qt.nokia.com/4.6/unix-signals.html":http://doc.qt.nokia.com/4.6/unix-signals.html

    bq.

    Firstly I the code is hard to get to compile to start with,
    and after a while when I got it compiling the QSocketNotifier don't seem to work.

    Can someone push me in the right direction on this topic?

    Thanks
    Johan

    1 Reply Last reply
    0
    • A Offline
      A Offline
      anselmolsm
      wrote on 12 Oct 2010, 13:50 last edited by
      #2

      Hi there!

      I read your question and got interested, since I've never needed to handle unix signals in a Qt app.

      [quote author="jsiei97" date="1286809378"]
      I tried to follow this example but it's not working for me.

      • "http://developer.qt.nokia.com/faq/answer/is_there_a_qt_way_to_handle_unix_posix_signals":http://developer.qt.nokia.com/faq/answer/is_there_a_qt_way_to_handle_unix_posix_signals
      • "http://doc.qt.nokia.com/4.6/unix-signals.html":http://doc.qt.nokia.com/4.6/unix-signals.html

      Firstly I the code is hard to get to compile to start with,
      [/quote]

      I followed the same instructions and example. Indeed, to build the example you need to know some things not mentioned in the doc + deal with static class members (not so obvious for C++ begginners, IMHO.).

      [quote author="jsiei97" date="1286809378"]
      and after a while when I got it compiling the QSocketNotifier don't seem to work.
      Can someone push me in the right direction on this topic?
      [/quote]

      Example built, I tested it successfully with both SIGTERM and SIGHUP. How did you test it?

      Maybe you did the same, but just to be sure, here is my test steps:

      run the example in a terminal, then in another terminal:

      for SIGHUP: kill -1 <example PID> or

      for SIGTERM: kill -15 <example PID>

      Anselmo L. S. Melo (anselmolsm)

      1 Reply Last reply
      0
      • J Offline
        J Offline
        jsiei97
        wrote on 12 Oct 2010, 14:55 last edited by
        #3

        I used the kill command, and got feedback from a print I added in the "unix signal handler function". But I never got any reaction in the Qt signal slot function that was supposed to run with some help from QSockerNotifier.

        And I also had to add some stuff, but I have no idea if I added the correct stuff...

        1 Reply Last reply
        0
        • A Offline
          A Offline
          anselmolsm
          wrote on 12 Oct 2010, 15:16 last edited by
          #4

          Ok, here is the example code + things added to build:

          • mydaemon.h:
            @
            #include <QSocketNotifier>

          class MyDaemon : public QObject
          {
          Q_OBJECT

          public:
          MyDaemon(QObject *parent = 0, const char *name = 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.cpp:
            @
            #include "mydaemon.h"

          #include <QDebug>
          #include <csignal>
          #include <sys/socket.h>

          //needed to not get an undefined reference to static members
          int MyDaemon::sighupFd[2];
          int MyDaemon::sigtermFd[2];

          MyDaemon::MyDaemon(QObject *parent, const char *name)
          : 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()));
          }

          MyDaemon::~MyDaemon() {}

          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;
          }

          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));
          }

          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);
          }
          @

          • main.cpp
            @
            #include <QCoreApplication>

          #include "mydaemon.h"

          int main(int argc, char *argv[])
          {
          QCoreApplication app(argc, argv);
          MyDaemon d;

          return app.exec&#40;&#41;;
          

          }
          @

          @jsiei97, I'll add stuff to the Qt slots and check.

          Anselmo L. S. Melo (anselmolsm)

          1 Reply Last reply
          0
          • J Offline
            J Offline
            jsiei97
            wrote on 12 Oct 2010, 16:53 last edited by
            #5

            Hi

            Your example is close, but who is calling setup_unix_signal_handlers()?
            I can't get any response with kill with your code.

            However I updated my with some parts that you added and got the code attached.

            And this code gave me this output

            @
            Qt and unix signals
            SIGHUP; kill -1 14795
            SIGTERM; kill -15 14795
            signal hup
            1signal hup
            1signal hup
            1signal hup
            1
            @

            Notice that strange '1' that seem to come from "snHup",
            but I never see the "real" print in MyDaemon::handleSigHup()...

            So I am a little confused here..

            main.cpp
            @
            #include <QCoreApplication>
            #include <QDebug>

            #include <signal.h>
            #include <unistd.h>

            #include "MyDaemon.h"

            static int setup_unix_signal_handlers()
            {
            int mypid = getpid();

            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;
            
            qDebug("SIGHUP; kill -%d %d", SIGHUP, mypid);
            
            term.sa_handler = MyDaemon::termSignalHandler;
            sigemptyset(&term.sa_mask);
            term.sa_flags |= SA_RESTART;
            
            if (sigaction(SIGTERM, &term, 0) > 0)
                return 2;
            
            qDebug("SIGTERM; kill -%d %d", SIGTERM, mypid);
            
            return 0;
            

            }

            /**

            • http://doc.trolltech.com/4.6/unix-signals.html
              */
              int main(int argc, char *argv[])
              {
              QCoreApplication app(argc, argv);
              qDebug() << "Qt and unix signals";

              setup_unix_signal_handlers();

              MyDaemon daemon();

              //while(1)
              //{
              // sleep(1);
              //}
              return app.exec();
              }
              @

            MyDaemon.h
            @
            #include <QObject>
            #include <QSocketNotifier>

            class MyDaemon : public QObject
            {
            Q_OBJECT

            public:
                MyDaemon(QObject *parent = 0, const char *name = 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.cpp
            @
            #include "MyDaemon.h"

            #include <QDebug>
            #include <QObject>
            #include <QSocketNotifier>
            #include <csignal>
            #include <sys/socket.h>

            //needed to not get an undefined reference to static members
            int MyDaemon::sighupFd[2];
            int MyDaemon::sigtermFd[2];

            MyDaemon::MyDaemon(QObject *parent, const char *name)
            : 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()));
            

            }

            MyDaemon::~MyDaemon() {}

            void MyDaemon::hupSignalHandler(int)
            {
            qDebug() << "signal hup";
            char a = '1';
            ::write(sighupFd[0], &a, sizeof(a));

            }

            void MyDaemon::termSignalHandler(int)
            {
            qDebug() << "signal term";
            char a = '2';
            ::write(sigtermFd[0], &a, sizeof(a));
            }

            void MyDaemon::handleSigTerm()
            {
            snTerm->setEnabled(false);
            char tmp;
            ::read(sigtermFd[1], &tmp, sizeof(tmp));

            // do Qt stuff
            qDebug() << "MyDaemon::handleSigTerm";
            
            snTerm->setEnabled(true);
            

            }

            void MyDaemon::handleSigHup()
            {
            snHup->setEnabled(false);
            char tmp;
            ::read(sighupFd[1], &tmp, sizeof(tmp));

            // do Qt stuff
            qDebug() << "MyDaemon::handleSigHup";
            
            snHup->setEnabled(true);
            

            }
            @

            1 Reply Last reply
            0
            • J Offline
              J Offline
              jsiei97
              wrote on 12 Oct 2010, 17:10 last edited by
              #6

              I noticed that I was calling the wrong constructor...?

              Adding some NULL as args was quite useful :)

              This is the working main function.
              @
              int main(int argc, char *argv[])
              {
              QCoreApplication app(argc, argv);
              qDebug() << "Qt and unix signals";

              setup_unix_signal_handlers();
              
              MyDaemon daemon(NULL,NULL);
              
              return app.exec();
              

              }
              @

              Thanks for the help.

              BR
              Johan

              1 Reply Last reply
              0
              • A Offline
                A Offline
                anselmolsm
                wrote on 12 Oct 2010, 19:39 last edited by
                #7

                gosh! I posted the wrong main.cpp - this was the first successfully built, not the tested one.
                Nice to see you solved it, I'll check later (/me answering from my mobile =)

                Anselmo L. S. Melo (anselmolsm)

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  anselmolsm
                  wrote on 14 Oct 2010, 17:30 last edited by
                  #8

                  Ok, now I can read the code properly in a bigger screen.

                  The correct main.cpp file looks like yours, the only difference is that I made setup_unix_signal_handlers() a static method of MyDaemon, then I call MyDaemon::setup_unix_signal_handlers() . But it is just a implementation detail (Yes, the mydaemon.h I posted here does not contains the correct declaration of such method... a problem of editing one file, copy-and-pasting another one).

                  One thing I did not understand is: why did you add NULL args when instantiating MyDaemon in your main.cpp?
                  AFAIK "in C++ NULL == 0":http://www2.research.att.com/~bs/bs_faq2.html#null, so as the default values for the MyDameon constructor are 0, it should not make any difference.

                  Anselmo L. S. Melo (anselmolsm)

                  1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    jsiei97
                    wrote on 15 Oct 2010, 07:07 last edited by
                    #9

                    why did you add NULL args when instantiating MyDaemon

                    That one is interesting, without them my program did not run the correct constructor.
                    So in my case the unix signal handler was not initialized, and the notifier and socket/slot was not setup correctly.

                    So I added (NULL, NULL) to match MyDaemon(QObject *parent, const char *name),
                    but I agree that it is strange that I needed to add this step.

                    Could it be that the program actually used some other constructor? Maybe one inherited from QObject? And that was why the compiler did not complain?

                    /Johan

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      anselmolsm
                      wrote on 15 Oct 2010, 11:11 last edited by
                      #10

                      [quote author="jsiei97" date="1287126448"]
                      Could it be that the program actually used some other constructor? Maybe one inherited from QObject? And that was why the compiler did not complain?
                      [/quote]

                      Hm... I don't know, need to look carefully, I'm curious now.

                      Anselmo L. S. Melo (anselmolsm)

                      1 Reply Last reply
                      0
                      • L Offline
                        L Offline
                        landrew
                        wrote on 24 Jan 2012, 23:28 last edited by
                        #11

                        Thanks for your post. I ran across it and am glad someone else had issues. In my case, the following post was very helpful in debugging. Thanks to this thread, I was able to compile and get my code working. :)

                        @
                        //needed to not get an undefined reference to static members
                        int MyDaemon::sighupFd[2];
                        int MyDaemon::sigtermFd[2];
                        @

                        1 Reply Last reply
                        0
                        • L Offline
                          L Offline
                          lanmanck
                          wrote on 9 May 2013, 02:25 last edited by
                          #12

                          I found it cannot inherit from QObject, the complier will report an error:undefined reference to vtable for XX.
                          Have you guys found this?

                          1 Reply Last reply
                          0
                          • S Offline
                            S Offline
                            ScumCoder
                            wrote on 20 Mar 2014, 14:26 last edited by
                            #13

                            It's because the compiler does not know that one of your classes is now QObject-inherited. Either rebuild the whole project from scratch, or modify your *.pro file (e.g. by typing a letter and deleting it) and then recompile.

                            [quote author="lanmanck" date="1368066317"]I found it cannot inherit from QObject, the complier will report an error:undefined reference to vtable for XX.
                            Have you guys found this?[/quote]

                            1 Reply Last reply
                            0

                            • Login

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved