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

Deadlock between SymbianEngine mutex and QNetworkConfigurationPrivate mutex in the symbian bearer code

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P0: Blocker
    • 4.7.3
    • 4.7.0
    • Symbian on S60. Emulator. Symbian internal release (10.1) week 38.
    • c15560fbe2a1762117395c5ecaaecfa5ab8dce6f

    Description

      In this code, in qt\src\plugins\bearer\symbian\symbianengine.cpp, the configuration mutex is locked via a QLocker:

      void SymbianEngine::updateStatesToSnaps()
      {
          // Go through SNAPs and set correct state to SNAPs
          foreach (const QString &iface, snapConfigurations.keys()) {
              bool discovered = false;
              bool active = false;
              QNetworkConfigurationPrivatePointer ptr = snapConfigurations.value(iface);
              QMutexLocker snapConfigLocker(&ptr->mutex);
              // => Check if one of the IAPs of the SNAP is discovered or active
              //    => If one of IAPs is active, also SNAP is active
              //    => If one of IAPs is discovered but none of the IAPs is active, SNAP is discovered
              QMapIterator<unsigned int, QNetworkConfigurationPrivatePointer> i(ptr->serviceNetworkMembers);
              while (i.hasNext()) {
                  i.next();
                  const QNetworkConfigurationPrivatePointer child = i.value();
                  QMutexLocker configLocker(&child->mutex);
                  if ((child->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
                      active = true;
                      break;
                  } else if ((child->state & QNetworkConfiguration::Discovered) ==
                             QNetworkConfiguration::Discovered) {
                      discovered = true;
                  }
              }
              if (active) {
                  changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
              } else if (discovered) {
                  changeConfigurationStateTo(ptr, QNetworkConfiguration::Discovered);
              } else {
                  changeConfigurationStateTo(ptr, QNetworkConfiguration::Defined);
              }
          }    
      }
      

      The above calls the below but I think that ptr->mutex will be locked on entry to the below function, locked because of the QLocker:

      bool SymbianEngine::changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr,
                                                     QNetworkConfiguration::StateFlags newState)
      {
          ptr->mutex.lock();
          if (newState != ptr->state) {
              ptr->state = newState;
              ptr->mutex.unlock();                                            // still locked here?
              mutex.unlock();
              emit configurationChanged(ptr);
              mutex.lock();
              return true;
          } else {
              ptr->mutex.unlock();
          }
          return false;
      }
      

      which means that the unlock where I have attached a comment will not do what the programmer intended.

      changeConfigurationStateTo(...) sends a signal which is handled by QNetworkConfigurationManagerPrivate. If another thread gets in and runs through the configurations via QNetworkConfigurationManagerPrivate::defaultConfiguration(...), then the second thread will have the QNetworkConfigurationManagerPrivate mutex locked and will wait on the configuration mutex, while the first thread will have the configuration mutex locked and will wait on the QNetworkConfigurationManagerPrivate mutex.

      Attachments

        Issue Links

          Activity

            People

              pepohjon Perttu Pohjonen
              john.beattie John Beattie
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: