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

occasional segmentation fault in processing of wireless networks

    XMLWordPrintable

Details

    • Linux/Yocto
    • 40b882d176 (qt/qtdeviceutilities/5.15) 05e26a13ee (qt/qtdeviceutilities/6.4) d0fa6b32b1 (qt/qtdeviceutilities/dev) 40b882d176 (qt/tqtc-qtdeviceutilities/5.15) 05e26a13ee (qt/tqtc-qtdeviceutilities/6.4) d0fa6b32b1 (qt/tqtc-qtdeviceutilities/dev)

    Description

      The QNetworkSettingsManagerPrivate class will occasionally produce a segmentation fault upon dereferencing a bad "d-pointer" within one of the QNetworkSettingsService items in its m_serviceModel list. I have seen this most often when attempting to read service->id() within QNetworkSettingsManagerPrivate::onServicesChanged(), but have also seen it happen elsewhere. This seems to happen on startup of the software application and be based on timing and the wireless networks available.

      I debugged this and found that bad QNetworkSettingsService objects representing wireless networks are sometimes added to the m_serviceModel even though they are scheduled to be deleted (and later are, while still existing in the m_serviceModel list), via the following sequence:

      1. connman notifies the network settings manager that a wireless network exists, via QNetworkSettingsManagerPrivate::onServicesChanged() ("changed" argument).
      2. The network of an unknown type is added to the m_unknownServices list, and its typeChanged() signal is connected to the QNetworkSettingsManagerPrivate::serviceReady() slot (in handleNewService()).
      3. connman notifies the network settings manager that the same wireless network should be removed, via QNetworkSettingsManagerPrivate::onServicesChanged() ("removed" argument).
      4. In onServicesChanged(), service->deleteLater() is called for the unknown service (and removed from m_unknownServices).
      5. Before the QNetworkSettingsService object is actually deleted, the event loop processes a QNetworkSettingsService::typeChanged() signal, which calls the QNetworkSettingsManagerPrivate::serviceReady() slot.
      6. Within the QNetworkSettingsManagerPrivate::serviceReady() slot, a pointer to the sender of the signal - which is the service object scheduled to be deleted - is retrieved via sender(). This is a dangerous pointer because the object is points to is scheduled to be deleted.
      7. The logic within serviceReady() leads to appending the pointer to the m_serviceModel list (m_serviceModel->append(service)) as if it is valid.
      8. The service object is eventually actually deleted, leaving a dangling pointer to freed memory in m_serviceModel (which might be later overwritten with other data).

      The serviceReady() slot really should not be called at all for an object scheduled to be deleted. Calling deleteLater() in #4 does not actually disconnect the signals from the service object - disconnections will not happen until the object is actually deleted.

      One potential solution is to manually disconnect the connections to the serviceReady() slot alongside the calls to deleteLater() in onServicesChanged(), e.g.:

      disconnect(service, &QNetworkSettingsService::nameChanged, this, &QNetworkSettingsManagerPrivate::serviceReady);
      disconnect(service, &QNetworkSettingsService::typeChanged, this, &QNetworkSettingsManagerPrivate::serviceReady);
      service->deleteLater();

      (Though it is not completely clear to me if there is additional logic needed for also clearing any pending events in the event queue. But I was no longer able to reproduce the problem with the above changes.)

      Other solutions / deeper design changes are also possible.

       

      Attachments

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

        Activity

          People

            jannej Janne Juntunen
            briandolan Brian Dolan
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: