Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-31606

QCoreApplication deadlock near posted events list

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 5.1.1
    • 5.0.2, 5.1.0 RC1
    • Core: Event loop
    • None
    • debian7 x64
    • d6d9edd7c47b183edc1acc631602ea4f4a885d84

    Description

      have QObject-based object (Receptor) with slot, accepted QSharedPointer of QObject-based object (Message)

      if
      1. Receptor.slot called through event loop (via signal emitting, via QMetaObject::invokeMethod, ...)
      2. Receptor.slot argument - QSharedPointer<Message> - have just one reference, holded into QMetaCallEvent
      3. Message object have undelivered posted events before call of Receptor.slot complete

      then deadlock occured during Message destruction, QObject destructor try to lock thread`s posted events list (for erase own undelivered events) but list already locked by delivering system

      reproduce

      #include <QtCore>
      
      class Receptor
              : public QObject
      {
          Q_OBJECT
      public:
          Receptor()
          {
              qRegisterMetaType<QSharedPointer<QObject> >("QSharedPointer<QObject>");
          }
      
      public slots:
      
      #if 1
          //deadlock
          void onMessage(QSharedPointer<QObject> msg=QSharedPointer<QObject>())
          {
              qDebug()<<"msg";
      
              //case 1: post any event to msg - deadlock
              //if(msg) QCoreApplication::instance()->postEvent(msg.data(), new QEvent(QEvent::None));
      
              QSharedPointer<QObject> newMsg(new QObject);
              QMetaObject::invokeMethod(this, "onMessage", Qt::QueuedConnection, Q_ARG(QSharedPointer<QObject>, newMsg));
      
              //case2: post any event to newMsg - deadlock
              QCoreApplication::instance()->postEvent(newMsg.data(), new QEvent(QEvent::None));
          }
      #else
          //workaround
          void onMessage(QSharedPointer<QObject> /*msg*/=QSharedPointer<QObject>())
          {
              qDebug()<<"msg";
      
              //QSharedPointer<QObject> newMsg(new Receptor, &QObject::deleteLater); //case3: deadlock
              QSharedPointer<QObject> newMsg(new Receptor, &defferedQObjectDeleter); //ok
              QMetaObject::invokeMethod(this, "onMessage", Qt::QueuedConnection, Q_ARG(QSharedPointer<QObject>, newMsg));
              QCoreApplication::instance()->postEvent(newMsg.data(), new QEvent(QEvent::None));
          }
      
          static void defferedQObjectDeleter(QObject *target)
          {
              QTimer::singleShot(1, target, SLOT(deleteLater()));
          }
      #endif
      };
      

      From user side defferedQObjectDeleter fix problem. From Qt side - see patch attached

      Attachments

        Activity

          People

            ogoffart Olivier Goffart (Woboq GmbH)
            vopl vopl
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: