QT GUI thread stuck when reading from /dev/input/event*

1k views Asked by At

I am running a QT embedded application(4.8.5) on arm, and found an issue that causes the GUI thread hung.

Below is the push button code.

const char* PushButtonService::m_eventfile = "/dev/input/event1";
PushButtonService::PushButtonService(QObject *parent): m_stop(false), m_pressed(false)
{
    m_sockfd = open(m_eventfile, O_RDONLY);
    m_notifier = new QSocketNotifier(m_sockfd, QSocketNotifier::Read, this);
    connect(m_notifier, SIGNAL(activated(int)), this, SLOT(readBtnEvts()));
    m_notifier->setEnabled(true);    
} 
void PushButtonService::readBtnEvts()
{
    QLOG_TRACE() << "read evts";
    struct input_event events[64];

QMutexLocker locker(&m_mutex);
int bytes = read(m_sockfd, events, sizeof(struct input_event));
if (bytes < (int) sizeof(struct input_event)) {
    QLOG_TRACE() << "no evts";
    return;
}

for (int i = 0; i < bytes / sizeof(struct input_event); i++){
    if (events[i].type == EV_KEY ) {
        if (events[i].value == 2) {
            if ( ! m_pressed ) {
                QLOG_TRACE() << "Emergency Pressed";
                emit emergencyPressed();
                m_pressed = true;
            }
        }else if (events[i].value == 0){
            if (m_pressed){
                QLOG_TRACE() << "Emergency Released";
                emit emergencyReleased();
                m_pressed = false;
            }
        }
    }
}
}
PushButtonService::~PushButtonService()
{
    close(m_sockfd);
    delete m_notifier;
}

Here is the GUI frame:

m_emergency_frame = new EmergencyFrame(this, m_language);
m_emergency_frame->hide();

m_push_button = new PushButtonService(this);
connect(m_push_button, SIGNAL(emergencyPressed()), this,    SLOT(emergencyPressed()));
connect(m_push_button, SIGNAL(emergencyReleased()), this, SLOT(emergencyReleased()));

void MainFerryFrame::emergencyPressed(){
QLOG_TRACE() << "Button pressed";
m_emergency_frame->show();
m_emergency_frame->raise();
}

 void MainFerryFrame::emergencyReleased()
{
    QLOG_TRACE() << "Button released";
    m_emergency_frame->hide();
}

I can get the push button event at the beginning, but after some repeats, the GUI application hung , and the backtrace when the application is :

(gdb) bt
#0  0xb650a378 in read () from /lib/arm-linux-gnueabihf/libpthread.so.0
#1  0xb69c81c0 in ?? () from /usr/lib/libQtGui.so.4
#2  0xb6632bf4 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib/libQtCore.so.4
#3  0xb6667f2a in QSocketNotifier::activated(int) () from /usr/lib/libQtCore.so.4
#4  0xb6638106 in QSocketNotifier::event(QEvent*) () from /usr/lib/libQtCore.so.4
#5  0xb69cf818 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4
#6  0xb69d123a in QApplication::notify(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4
#7  0x000d7028 in ?? ()
Cannot access memory at address 0x2044
#8  0x000d7028 in ?? ()
Cannot access memory at address 0x2044
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Any clues?

1

There are 1 answers

1
UmNyobe On
m_sockfd = open(m_eventfile, O_RDONLY);

I believe this will perform blocking reads unless O_NONBLOCK is set. This is due to the fact that when you are notified, nothing guarantee that 64 events are available.

You should probably execute PushButtonService objects in their own Qthread.

m_push_button = new PushButtonService(0);
m_service_thread = new QThread();

m_push_button->moveToThread(m_service_thread);

You will have to move all setup of the PushButtonService constructor in a slot (ie bootstrap), and connect it to the start signal of the QThread.