Signal slots not working when QApplication.exec



  • The following code generates a test message:

    @
    Sender lSender;
    Receiver lReceiver;

    QObject::connect(&lSender,
    

    SIGNAL(Send(const QString&)),
    &lReceiver,
    SLOT(Receive(const QString &))
    );

    lSender.SendSomeMessages();
    lSender.SendSomeMessages();
    

    @

    Sender:
    @
    void Sender::SendSomeMessages()
    {
    QString lTestMessage = "1234";
    emit Send(lTestMessage);
    emit Send(lTestMessage);
    emit Send(lTestMessage);
    emit Send(lTestMessage);
    }
    @

    Receiver:
    @
    class Receiver : public QObject
    {
    Q_OBJECT
    public:
    Receiver();
    virtual ~Receiver();
    public slots:
    void Receive(const QString & aString);
    };
    @

    @
    void Receiver::Receive(const QString & aString)
    {
    LOG_INFO(mLogHelper) << aString.toStdString();
    printf(aString.toUtf8().constData());
    }
    @

    When using the following code the slot is not called anymore!

    main.cpp:
    @
    QApplication lApp(argc, argv);

    Sender lSender;
    Receiver lReceiver;
    
    QObject::connect(&lSender,
    

    SIGNAL(Send(const QString&)),
    &lReceiver,
    SLOT(Receive(const QString &))
    );

    lSender.SendSomeMessages();
    lSender.SendSomeMessages();
    
    return lApp.exec&#40;&#41;;
    

    @

    What's going wrong?


  • Moderators

    You cannot send messages before the event loop is started with "exec":http://developer.qt.nokia.com/doc/qt-4.8/qapplication.html#exec
    See also "signal and slots":http://developer.qt.nokia.com/doc/qt-4.8/signalsandslots.html



  • [quote author="koahnig" date="1326386034"]You cannot send messages before the event loop is started with "exec":http://developer.qt.nokia.com/doc/qt-4.8/qapplication.html#exec
    See also "signal and slots":http://developer.qt.nokia.com/doc/qt-4.8/signalsandslots.html [/quote]

    Well, that's not exactly true. <code>Qt::DirectConnection</code> does not require an event loop at all, <code>Qt::QueuedConnection</code> can be emitted without an event loop, but does need an event loop to be dispatched. If there is no event loop running at the time they are emitted, the signals are queued and dispatched as soon as an event loop starts. No signals are lost if there is no event loop running.

    Your code works perfectly for me.
    @
    class Sender : public QObject
    {
    Q_OBJECT

    public:
    void SendSomeMessages()
    {
    emit Send("1234");
    emit Send("1234");
    emit Send("1234");
    emit Send("1234");
    }

    signals:
    void Send(const QString&);
    };

    class Receiver : public QObject
    {
    Q_OBJECT

    public slots:
    void Receive(const QString &string)
    {
    qDebug() << string;
    }
    };

    int main(int argc, char *argv[])
    {
    QApplication application(argc, argv);

    Sender sender;
    Receiver receiver;
    
    QObject::connect(&sender, SIGNAL(Send(const QString&)), 
                     &receiver, SLOT(Receive(const QString&)));
    
    sender.SendSomeMessages();
    
    return application.exec(&#41;;
    

    }
    @

    You might provide a small, compileable example that reproduces your problem for further assistance.



  • It doesn't work here... Code:

    main.cpp:
    @
    #include <QtCore>
    #include <QCoreApplication>
    #include "Sender.h"
    #include "Receiver.h"

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);
    printf("test");

    Sender lSender;
    Receiver lReceiver;
    
    QObject::connect(&lSender,
                                     SIGNAL(Send(const QString&)),
                                     &lReceiver,
                                     SLOT(Receive(const QString &))
                                     );
    
    lSender.SendSomeMessages();
    
    return a.exec&#40;&#41;;
    

    }
    @

    Sender.h:
    @
    #include <QString>
    #include <QObject>

    class Sender : public QObject
    {
    Q_OBJECT
    public:
    Sender();
    virtual ~Sender();

        void SendSomeMessages();
    

    signals:
    void Send(const QString & aString);
    };
    @

    Sender.cpp:
    @
    Sender::Sender() {
    // TODO Auto-generated constructor stub

    }

    Sender::~Sender() {
    // TODO Auto-generated destructor stub
    }

    void Sender::SendSomeMessages()
    {
    QString lTestMessage = "1234";
    emit Send(lTestMessage);
    emit Send(lTestMessage);
    emit Send(lTestMessage);
    emit Send(lTestMessage);
    }
    @

    Receiver.h:
    @
    #include <QObject>
    #include <QString>

    class Receiver : public QObject
    {
    Q_OBJECT
    public:
    Receiver();
    virtual ~Receiver();

    public slots:
    void Receive(const QString & aString);
    };
    @

    Receiver.cpp:
    @
    #include "Receiver.h"

    Receiver::Receiver() {
    // TODO Auto-generated constructor stub

    }

    Receiver::~Receiver() {
    // TODO Auto-generated destructor stub
    }

    void Receiver::Receive(const QString & aString)
    {
    printf(aString.toUtf8().constData());
    }
    @

    Actually I asked this question because on my target device it seems the signals are queued and when i press a certain hardware button the queued is pushed. On my host (pc, same code) the signals are not queued. I use the following pseudo code:

    @
    QApplication lApp(argc, argv);
    QDeclarativeView lView;
    QDeclarativeContext *lContext = lView.rootContext();
    lView.setSource(lMainQMLFile);
    lView.show();

    Connect some signals and slots

    lApp.exec();
    @

    After this when i trigger a signal the signal is queued. When i press some hardware buttons the signals are pushed.

    I tried to do some testing by making a small test app. I noticed that the signals are pushed whenever I removed the lApp.exec()! Which seems odd to me because according to the docs it should only work when lApp.exec() is called.

    Btw: I use Qt:QueuedConnections!

    Any suggestions?


  • Moderators

    [quote author="Lukas Geyer" date="1326393782"]
    Well, that's not exactly true. <code>Qt::DirectConnection</code> does not require an event loop at all, <code>Qt::QueuedConnection</code> can be emitted without an event loop, but does need an event loop to be dispatched. If there is no event loop running at the time they are emitted, the signals are queued and dispatched as soon as an event loop starts. No signals are lost because there is no event loop running.
    [/quote]

    Thanks for correcting my view



  • [quote author="bkamps" date="1326395757"]It doesn't work here... Code:
    Actually I asked this question because on my target device it seems the signals are queued and when i press a certain hardware button the queued is pushed.
    ...
    I tried to do some testing by making a small test app. I noticed that the signals are pushed whenever I removed the lApp.exec()! Which seems odd to me because according to the docs it should only work when lApp.exec() is called.
    [/quote]

    <code>QCoreApplication::exec()</code> is vital when it comes to dispatching <code>Qt::QueuedConnection</code> signals. I doubt that this behaviour is caused by the code you've posted. It seems like <code>QCoreApplication::exec()</code> stalls, most probably at some system call, and thus no event processing and signal dispatching is happening.

    I would start with a small test application and step through / halt at <code>QCoreApplication::exec()</code> to see where it stalls.
    @
    int main(int argc, char *argv[])
    {
    QCoreApplication application(argc, argv);

    QMetaObject::invokeMethod(&application, "quit", Qt::QueuedConnection&#41;;
    application.exec(&#41;;
    
    // If you reach this code path you have event processing, if not,
    // QCoreApplcation::exec(&#41; is stalled and you should halt and 
    // investigate further.
    
    return 0;
    

    }
    @

    What kind of hardware device are we talking about here?



  • It's a custom ARM-device. I have come a litle further:

    When I use QCoreApplication::exec the event queue is processed. When I use QApplication the event queue does only respond when I press one of my hardware buttons...

    I use a GUI application so normally I use QApplication (as described bt Qt docs).



  • Have you tried stepping through to see where it actually stalls?



  • I have the backtrace at last. Unfortunately I cannot see why qt_safe_read doesn't return:

    @
    Program received signal SIGINT, Interrupt.
    0x414fac4c in ?? ()
    (gdb) bt
    #0 0x414fac4c in ?? ()
    #1 0x401ee450 in qt_safe_read (fd=25, data=0xbebcb1cc, maxlen=32)
    at ../../include/QtCore/private/../../../../package/src/corelib/kernel/qcore_unix_p.h:253
    #2 0x401ee504 in QWSTtyKbPrivate::readKeycode (this=0x25ac0)
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/gui/embedded/qkbdtty_qws.cpp:243
    #3 0x401ee948 in QWSTtyKbPrivate::qt_metacall (this=0x25ac0, _c=QMetaObject::InvokeMetaMethod, _id=0, _a=0xbebcb320)
    at .moc/debug-shared-emb-arm/qkbdtty_qws.moc:73
    #4 0x412ff218 in QMetaObject::metacall (object=0x25ac0, cl=QMetaObject::InvokeMetaMethod, idx=4, argv=0xbebcb320)
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/corelib/kernel/qmetaobject.cpp:237
    #5 0x4131a628 in QMetaObject::activate (sender=0x2c1e0, m=0x414e8e20, local_signal_index=0, argv=0xbebcb320)
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/corelib/kernel/qobject.cpp:3275
    #6 0x413ae7bc in QSocketNotifier::activated (this=0x2c1e0, _t1=25) at .moc/debug-shared-emb-arm/moc_qsocketnotifier.cpp:89
    #7 0x4132797c in QSocketNotifier::event (this=0x2c1e0, e=0xbebcb970)
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/corelib/kernel/qsocketnotifier.cpp:317
    #8 0x401fe1c4 in QApplicationPrivate::notify_helper (this=0x13c68, receiver=0x2c1e0, e=0xbebcb970)
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/gui/kernel/qapplication.cpp:4462
    #9 0x401fe8ec in QApplication::notify (this=0xbebcbc40, receiver=0x2c1e0, e=0xbebcb970)
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/gui/kernel/qapplication.cpp:3862
    #10 0x412f4084 in QCoreApplication::notifyInternal (this=0xbebcbc40, receiver=0x2c1e0, event=0xbebcb970)
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/corelib/kernel/qcoreapplication.cpp:731
    #11 0x401fa018 in QCoreApplication::sendEvent (receiver=0x2c1e0, event=0xbebcb970)
    at ../../include/QtCore/../../../package/src/corelib/kernel/qcoreapplication.h:215
    #12 0x413434c0 in QEventDispatcherUNIX::activateSocketNotifiers (this=0x138d8)
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/corelib/kernel/qeventdispatcher_unix.cpp:877
    #13 0x41346538 in QEventDispatcherUNIXPrivate::doSelect (this=0x13fe0, flags={i = -1094927632}, timeout=0xbebcbae0)
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/corelib/kernel/qeventdispatcher_unix.cpp:305
    #14 0x41346770 in QEventDispatcherUNIX::processEvents (this=0x138d8, flags={i = -1094927560})
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/corelib/kernel/qeventdispatcher_unix.cpp:919
    #15 0x402e126c in QEventDispatcherQWS::processEvents (this=0x138d8, flags={i = -1094927504})
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/gui/kernel/qeventdispatcher_qws.cpp:132
    #16 0x412ef4ec in QEventLoop::processEvents (this=0xbebcbbdc, flags={i = -1094927452})
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/corelib/kernel/qeventloop.cpp:149
    #17 0x412ef82c in QEventLoop::exec (this=0xbebcbbdc, flags={i = -1094927388})
    at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/corelib/kernel/qeventloop.cpp:197
    #18 0x412f4c24 in QCoreApplication::exec () at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/corelib/kernel/qcoreapplication.cpp:1008
    #19 0x40201678 in QApplication::exec () at /home/dm051/repository/sw/cscis/tni_delivery/build/qt/package/src/gui/kernel/qapplication.cpp:3736
    #20 0x00009614 in main (argc=1, argv=0xbebcbda4) at ../main/main.cpp:20
    @



  • To be absolutely sure I don't have a wrong text I repost the source code I use:

    main.cpp:
    @
    int main(int argc, char *argv[])
    {
    QApplication lApp(argc, argv);
    Sender lSender;
    lSender.SendSomeMessages();

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

    }
    @

    Sender.cpp:
    @
    #include "Sender.h"

    Sender::Sender():
    mTimer()
    {
    }

    Sender::~Sender()
    {
    }

    void Sender::SendSomeMessages()
    {
    connect(&mTimer, SIGNAL(timeout()), this, SLOT(OnTimer()));
    mTimer.setSingleShot(false);
    mTimer.start(1000);
    }

    void Sender::OnTimer()
    {
    printf("Timer called\r\n");
    }
    @

    Sender.h:
    @
    class Sender : public QObject
    {
    Q_OBJECT
    public:
    Sender();
    virtual ~Sender();

    void SendSomeMessages();

    signals:
    void Send(const QString & aString);

    public slots:
    void OnTimer();

    private:
    QTimer mTimer;

    };
    @



  • Got a little further using strace tool.

    Normal working situation:

    @
    clock_gettime(CLOCK_MONOTONIC, {4784, 169698261}) = 0
    clock_gettime(CLOCK_MONOTONIC, {4784, 171872021}) = 0
    clock_gettime(CLOCK_MONOTONIC, {4784, 174807641}) = 0
    select(15, [6 10 13 14], [], [], {0, 981605}) = 0 (Timeout)
    clock_gettime(CLOCK_MONOTONIC, {4785, 162668064}) = 0
    write(1, "Timer called\r\n", 14Timer called
    ) = 14
    clock_gettime(CLOCK_MONOTONIC, {4785, 168837422}) = 0
    clock_gettime(CLOCK_MONOTONIC, {4785, 171772478}) = 0
    clock_gettime(CLOCK_MONOTONIC, {4785, 175237983}) = 0
    select(15, [6 10 13 14], [], [], {0, 982466}) = 0 (Timeout)
    clock_gettime(CLOCK_MONOTONIC, {4786, 163562222}) = 0
    write(1, "Timer called\r\n", 14Timer called
    ) = 14
    @

    When a hardware key is pressed:
    @
    clock_gettime(CLOCK_MONOTONIC, {4786, 168694880}) = 0
    clock_gettime(CLOCK_MONOTONIC, {4786, 170878300}) = 0
    clock_gettime(CLOCK_MONOTONIC, {4786, 173212682}) = 0
    select(15, [6 10 13 14], [], [], {0, 982609}) = 1 (in [13], left {0, 435102})
    read(13, <<<<<<<<<<<<<<<<<<<<<< BLOCKING
    @

    When another hardware key is pressed the timer is running again:
    @
    clock_gettime(CLOCK_MONOTONIC, {4786, 168694880}) = 0
    clock_gettime(CLOCK_MONOTONIC, {4786, 170878300}) = 0
    clock_gettime(CLOCK_MONOTONIC, {4786, 173212682}) = 0
    select(15, [6 10 13 14], [], [], {0, 982609}) = 1 (in [13], left {0, 435102})
    read(13, "\n", 32) = 1
    @

    So it seems some of the hardware keys interfere with pipes that Qt uses for its event queue... Also the read gives readable data like:

    @
    read(13, "\212", 32) = 1
    read(13, "\n", 32) = 1
    read(13, "\204", 32) = 1
    @

    So I guess the linux key driver is doing some dirty stuff in my process memory space...



  • This is rather strange.



  • Hehe yeah, tell me! Going to discuss this with our hardware/bsp supplier...



  • Updated the BSP and the problem magically disappears! THANK GOD :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.