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

when use QDBusAbstractInterface::call with QDBus::BlockWithGui callmode, has chance to make the send thread can't quit the local eventloop forever

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P4: Low
    • 6.7.0 FF
    • 5.9
    • D-Bus
    • None
    • Linux/Wayland
    • 24e504d9df16537f8a3f7d69a917ddb43b6e82d3

    Description

      when use qdbus, like this

      myQDBusInterface->call(QDBus::BlockWithGui, ......)

      I encountered such a problem that the functions call never returns,and it should be timeout but it doesn't.

      finally, I found what's wrong it is.  the core logic of the function "QDBusAbstractInterface::call" like this,  

      // send thread                                       // QDBusConnectionManager  thread
      QDBusConnectionPrivate::sendWithReply
           QDBusConnectionPrivate::sendWithReplyAsync
                emit messageNeedsSending             ----> QDBusConnectionPrivate::sendInternal
           create QDBusPendingCallWatcherHelper                q_dbus_connection_send_with_reply
           Qeventloop.exec                                     q_dbus_pending_call_set_notify

      send dbus message、register result callback and call the callback  function for reply message are all in QDBusConnectionManager thread, and create QDBusPendingCallWatcherHelper and wating in Qeventloop is in send thread. when reply message returned, the QDBusPendingCallWatcherHelper will be used to sigal the send thread to quit Qeventloop.

      If the reply message returned is earlier than QDBusPendingCallWatcherHelper created, the send thread will never quit Qeventloop.

      For reproduce this case, we can force the send thread to sleep a short time to make the reply message returned earlier.

      QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,                                                   int sendMode, int timeout){    QDBusBlockingCallWatcher watcher(message);
          QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, 0, 0, 0, timeout);    Q_ASSERT(pcall);
          if (pcall->replyMessage.type() == QDBusMessage::InvalidMessage) {    QThread::msleep(100);    // need to wait for the reply        if (sendMode == QDBus::BlockWithGui) {            pcall->watcherHelper = new QDBusPendingCallWatcherHelper;
      

      And I fixed the problem like this:

      @@ -2046,15 +2050,15 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,
           QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, 0, 0, 0, timeout);
           Q_ASSERT(pcall);+    QEventLoop loop;
      +    if (sendMode == QDBus::BlockWithGui) {
      +        pcall->watcherHelper = new QDBusPendingCallWatcherHelper;
      +        loop.connect(pcall->watcherHelper, &QDBusPendingCallWatcherHelper::reply, &loop, &QEventLoop::quit);
      +        loop.connect(pcall->watcherHelper, &QDBusPendingCallWatcherHelper::error, &loop, &QEventLoop::quit);
      +    }
      +
           if (pcall->replyMessage.type() == QDBusMessage::InvalidMessage) {
      -        // need to wait for the reply
               if (sendMode == QDBus::BlockWithGui) {
      -            pcall->watcherHelper = new QDBusPendingCallWatcherHelper;
      -            QEventLoop loop;
      -            loop.connect(pcall->watcherHelper, &QDBusPendingCallWatcherHelper::reply, &loop, &QEventLoop::quit);
      -            loop.connect(pcall->watcherHelper, &QDBusPendingCallWatcherHelper::error, &loop, &QEventLoop::quit);
      -
      -            // enter the event loop and wait for a reply
                   loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents);
               } else {
                   pcall->waitForFinished();
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            thiago Thiago Macieira
            lgclylyx lgclylyx
            Vladimir Minenko Vladimir Minenko
            Alex Blasche Alex Blasche
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews