Strange behaviour of signal/slot with QLocalSocket on Qt embedded on x86 board



  • Hi all,
    I'm trying to make a small program that detect the power button event.

    The platform I'm working on is an x86 Atom board that runs Ubuntu Server 12.04, with Qt embedded v4.8 (I use embedded version because I need to run my applications in framebuffer).
    I compiled the Qt framework using these command line arguments:
    @./configure -prefix /usr/local -no-largefile -no-accessibility -no-qt3support -no-xmlpatterns -platform qws/linux-x86-g++ -no-cups -dbus -embedded x86 -qt-gfx linuxfb -qt-mouse-tslib -system-zlib -system-libtiff -system-libpng -system-libjpeg -no-pch -no-openssl -no-declarative -no-declarative-debug -no-webkit -no-javascript-jit -no-script -no-scripttools -nomake demos -nomake examples@

    I've coded a small program that listens for ACPI events on /var/run/acpid.socket (this is the unix socket used by the acpid daemon, and everytime I push the power button the acpid daemon writes onto this socket).

    I add my code below:

    @
    // TestQtAcpi.pro

    #-------------------------------------------------

    Project created by QtCreator 2013-01-14T17:13:28

    #-------------------------------------------------

    QT += core gui network

    SOURCES += main.cpp
    mainwindow.cpp
    HEADERS += mainwindow.h
    FORMS += mainwindow.ui

    TEMPLATE = app
    @

    @
    // main.cpp

    #include <QtGui/QApplication>
    #ifdef Q_WS_QWS
    #include <QWSServer>
    #endif
    #include "mainwindow.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MainWindow w;
    #ifdef Q_WS_QWS
    QWSServer::setCursorVisible( false );
    w.showFullScreen();
    #else
    w.show();
    #endif

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

    }
    @

    @
    // mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QtNetwork/QLocalSocket>

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    int count;
    QLocalSocket *socket;

    private:
    Ui::MainWindow *ui;

    public slots:
    void onSocketDataReady();
    void onSocketError(QLocalSocket::LocalSocketError);
    };

    #endif // MAINWINDOW_H
    @

    @
    // mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    #ifdef _WIN32
    #define SOCKET_NAME "\\.\pipe\foo"
    #endif

    #ifdef linux
    #define SOCKET_NAME "/var/run/acpid.socket"
    #endif

    #include <QDebug>

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    count = 0;
    socket = new QLocalSocket(this);

    connect(socket, SIGNAL(readyRead()), this, SLOT(onSocketDataReady()));
    connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(onSocketError(QLocalSocket::LocalSocketError)));
    
    socket->connectToServer(SOCKET_NAME, QIODevice::ReadOnly);
    if (socket->waitForConnected(1000))
         qDebug("Connected!");
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::onSocketDataReady()
    {
    QString data(socket->readAll());
    count++;
    ui->labelCount->setText(QString::number(count));
    if(data.contains(QString("button/power")))
    qDebug("PowerButton pressed detected!");
    }

    void MainWindow::onSocketError(QLocalSocket::LocalSocketError error)
    {
    qDebug() << "Socket Error: " << error;
    }
    @

    Basically, the program opens a socket on /var/run/acpid.socket using QLocalSocket object, and every time that there are some bytes available on that socket the readyRead event is triggered and the slot onSocketDataReady should be called. Inside this slot, a counter is incremented and a label on the GUI is updated (just to show that the slot has being called).

    I've tested this program on my windows machine (I wrote another program that uses QLocalServer to emulate the behaviour of the linux acpid daemon) and the application works as expected, every time there are data on the socket the slot is called and executed.

    Running the application on the linux machine with Qt embedded leads to strange behaviour, the slot is not always called. I'm not saying that the slot is never called, sometimes it is called and sometimes not...
    I'll try to explain better what's happening:
    I run the program on the embedded board, then I start to press the power button to see if it detects correctly the events, at this point the situation is that the counter is not incremented at every button press, sometimes I need to press the button 3 or 4 times to see the counter increment (and thus the slot being called), sometimes it increments immediatly after the button press, but this behaviour is not predictable and I don't understand which is the cause of this problem...

    Any help/suggestions are really appreciated!

    Samuele.



  • Just for clarification, the ACPI daemon works correctly, and the test I'm doing seems to be correct because the same version of this program that runs on the console (without a GUI frontend) works as expected!

    @
    // TestQtAcpi

    #-------------------------------------------------

    Project created by QtCreator 2013-01-14T17:13:28

    #-------------------------------------------------

    CONFIG += gui

    QT += core network
    QT -= gui

    TARGET = TestQtAcpi

    CONFIG += console
    CONFIG -= app_bundle

    SOURCES += main.cpp mainconsole.cpp
    HEADERS += mainconsole.h

    TEMPLATE = app
    @

    @
    // main.cpp

    #include <QtCore/QCoreApplication>
    #include "mainconsole.h"

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

    MainConsole w;
    
    return a.exec&#40;&#41;;
    

    }
    @

    @
    // mainconsole.h

    #ifndef MAINCONSOLE_H
    #define MAINCONSOLE_H

    #include <QObject>
    #include <QtNetwork/QLocalSocket>

    class MainConsole : public QObject
    {
    Q_OBJECT
    public:
    explicit MainConsole(QObject *parent = 0);
    ~MainConsole();

    private:
    QLocalSocket *socket;

    public slots:
    void onSocketDataReady();
    void onSocketError(QLocalSocket::LocalSocketError);
    };

    #endif // MAINCONSOLE_H
    @

    @
    // mainconsole.cpp

    #include "mainconsole.h"
    #include <QtNetwork/QLocalSocket>

    #ifdef _WIN32
    #define SOCKET_NAME "\\.\pipe\foo"
    #endif

    #ifdef linux
    #define SOCKET_NAME "/var/run/acpid.socket"
    #endif

    #include <QDebug>

    MainConsole::MainConsole(QObject *parent) :
    QObject(parent)
    {
    socket = new QLocalSocket(this);
    connect(socket, SIGNAL(readyRead()), this, SLOT(onSocketDataReady()));
    connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(onSocketError(QLocalSocket::LocalSocketError)));

    socket->connectToServer(SOCKET_NAME, QIODevice::ReadOnly);
    if (socket->waitForConnected(1000))
        qDebug("Connected!");
    

    }

    MainConsole::~MainConsole()
    {

    }

    void MainConsole::onSocketDataReady()
    {
    QString data(socket->readAll());
    if(data.contains(QString("button/power")))
    qDebug("PowerButton pressed detected!");
    }

    void MainConsole::onSocketError(QLocalSocket::LocalSocketError error)
    {
    qDebug() << "Socket Error: " << error;
    }
    @

    This console version of the program works as expected, everytime I press the power button it calls the slot and prints "PowerButton pressed detected!" on the console.

    I can't understand what is the difference in the signal/slot calling procedure between the GUI version and the console version of this program... in my program I have the need to display a GUI, so I need to make the GUI version working correctly.


Log in to reply
 

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