Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Multithread applications blocking when using QDBus::BlockWithGui
Forum Updated to NodeBB v4.3 + New Features

Multithread applications blocking when using QDBus::BlockWithGui

Scheduled Pinned Locked Moved Unsolved General and Desktop
3 Posts 2 Posters 648 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.
  • N Offline
    N Offline
    Narveth
    wrote on last edited by Narveth
    #1

    Hello,

    I am using Qt 5.13 to develop a linux multithread application with DBus.

    Each thread is calling a dbus method in a loop, and I want to use the QBus::CallMode "BlockWithGui" to prevent any blocking so that I can use signals and slots and keep using the event loop in threads.

    When I don't use this mode, everything goes ok. But when I use it, one of the thread always get blocked at some point.

    The code pasted is just a sample so that you can easily test and it only reflects the problem I am having in my application.

    CMakeLists.txt

    CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
    
    PROJECT(scenario-test)
    
    FIND_PACKAGE(Qt5 COMPONENTS Core DBus Concurrent REQUIRED)
    
    SET(CMAKE_INCLUDE_CURRENT_DIR ON)
    
    
    set(${PROJECT_NAME}_moc_headers
     WorkerThread.hh
    )
    
    SET(${PROJECT_NAME}_HEADERS
      ${${PROJECT_NAME}_moc_headers}
    )
    
    qt5_wrap_cpp(${PROJECT_NAME}_mocs ${${PROJECT_NAME}_moc_headers})
    
    SET(${PROJECT_NAME}_SOURCES
      main.cpp
      WorkerThread.cpp
    )
    
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -pthread")
    
    
    ADD_EXECUTABLE(${PROJECT_NAME} ${${PROJECT_NAME}_SOURCES} ${${PROJECT_NAME}_HEADERS} ${${PROJECT_NAME}_mocs})
    
    target_link_libraries(${PROJECT_NAME} ${QJSONLIB} dl Qt5::Core Qt5::DBus)
    
    INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
    INSTALL(FILES ${${PROJECT_NAME}_HEADERS} DESTINATION "include/${PROJECT_NAME}")
    

    main.cpp

    #include <QtCore/QCoreApplication>
    #include <QTimer>
    #include <QThread>
    #include <QDebug>
    #include <QVector>
    #include <QDBusConnection>
    #include "WorkerThread.hh"
    
    int main(int ac, char** av)
    {
      QCoreApplication app(ac, av);
      QCoreApplication::setApplicationName("scenario-test");
    
      QTimer::singleShot(0, []() {
          QVector<QThread *> threads;
    
          if (!QDBusConnection::sessionBus().isConnected()) {
              qCritical() << "Cannot connect to the D-Bus system bus.\n"
                          << "please check your system settings and try again.\n";
              return;
            }
          for (int i = 0; i < 2; i++)
            {
              WorkerThread *worker = new WorkerThread();
              QThread *thread = new QThread();
    
              worker->moveToThread(thread);
              QObject::connect(thread, &QThread::finished, worker, &QObject::deleteLater);
              QObject::connect(thread, &QThread::started, worker, &WorkerThread::run);
              thread->start();
              threads.push_back(thread);
            }
          for (int i = 0; i < 2; i++)
            {
            qDebug() << "Waiting for thread id : " << i;
            threads[i]->wait();
            qDebug() << "Done waiting for thread id : "  << i;
            threads[i]->quit();
          }
           QCoreApplication::quit();
        });
      int status = app.exec();
      qDebug() << "Finished";
      return status;
    }
    

    WorkerThread.hh

    #pragma once
    
    #include <QThread>
    #include <QObject>
    #include <QDebug>
    #include <QDBusInterface>
    
    class WorkerThread : public QObject
    {
      Q_OBJECT
      public:
      WorkerThread(QObject* parent = nullptr);
    
      ~WorkerThread();
    
    public slots:
      void run();
    };
    

    WorkerThread.cpp

    #include <QDBusError>
    #include <QTimer>
    #include <QDBusInterface>
    #include "WorkerThread.hh"
    #include <QDBusReply>
    #include <QJsonDocument>
    #include <QJsonObject>
    
    WorkerThread::WorkerThread(QObject* parent):
      QObject(parent)
    {}
    
    WorkerThread::~WorkerThread() {}
    
    void WorkerThread::run()
    {
      for (int i = 0; i < 100; ++i)
        {
          qDebug() <<  "[" << QThread::currentThread() << "] call before";
          QDBusInterface  inter("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", QDBusConnection::sessionBus());
          auto namesList = inter.call(QDBus::BlockWithGui, "ListNames").arguments().at(0).toList();
          qDebug() <<  "[" << QThread::currentThread() << "] call after";
        }
      QThread::currentThread()->quit();
    }
    
    

    After compiling, you can run the executable until the blocking appears. I see one of the thread is stuck at "call before" but does not print "call after", it looks like its event loop is stuck.

    Do you guys have any idea why using this QDBus mode is blocking thread at some point ?

    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      I would guess that the underlying QDBusInterface stuff is not threadsafe so you will get into a deadlock.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      0
      • N Offline
        N Offline
        Narveth
        wrote on last edited by
        #3

        Hmm I hope its not the case because in my real application the DBus service I am calling can respond 10 seconds later, and I need to be able calling it in multiple threads...

        I have try to make a shared instance of QDBusInterface in the WorkerThread class and use a mutex :

        WorkerThread.hh

        #pragma once
        
        #include <QThread>
        #include <QObject>
        #include <QDebug>
        #include <QDBusInterface>
        #include <QMutex>
        
        class WorkerThread : public QObject
        {
          Q_OBJECT
          public:
          WorkerThread(QObject* parent = nullptr);
        
          ~WorkerThread();
        
        public slots:
          void run();
        
        private:
        
          static QDBusInterface *_iface;
          static QMutex        _mutex;
        
        };
        
        

        WorkerThread.cpp

        #include <QDBusError>
        #include <QTimer>
        #include <QDBusInterface>
        #include "WorkerThread.hh"
        #include <QDBusReply>
        #include <QJsonDocument>
        #include <QJsonObject>
        
        QDBusInterface *WorkerThread::_iface = new QDBusInterface("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", QDBusConnection::sessionBus());
        
        QMutex WorkerThread::_mutex;
        
        WorkerThread::WorkerThread(QObject* parent):
          QObject(parent)
        {}
        
        WorkerThread::~WorkerThread() {}
        
        void WorkerThread::run()
        {
          for (int i = 0; i < 100; ++i)
            {
              qDebug() <<  "[" << QThread::currentThread() << "] call before";
              this->_mutex.lock();
              auto namesList = this->_iface->call(QDBus::BlockWithGui, "ListNames").arguments().at(0).toList();
              this->_mutex.unlock();
              qDebug() <<  "[" << QThread::currentThread() << "] call after";
            }
          QThread::currentThread()->quit();
        }
        
        

        But it does not solve the problem either, sometimes one thread is still blocked.

        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