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.3k 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.
  • A Offline
    A Offline
    anselmolsm
    wrote on 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 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 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 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 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 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 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 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 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 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