diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp index 787259fd659..e93da4eaec8 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp @@ -3,6 +3,10 @@ #include "qnetworklistmanagerevents.h" +#include + +#include + #ifdef SUPPORTS_WINRT #include #include @@ -102,11 +106,16 @@ bool QNetworkListManagerEvents::start() #ifdef SUPPORTS_WINRT using namespace winrt::Windows::Networking::Connectivity; + using winrt::Windows::Foundation::IInspectable; // Register for changes in the network and store a token to unregister later: token = NetworkInformation::NetworkStatusChanged( - [this](const winrt::Windows::Foundation::IInspectable sender) { + [owner = QPointer(this)](const IInspectable sender) { Q_UNUSED(sender); - emitWinRTUpdates(); + if (owner) { + std::scoped_lock locker(owner->winrtLock); + if (owner->token) + owner->emitWinRTUpdates(); + } }); // Emit initial state emitWinRTUpdates(); @@ -115,24 +124,28 @@ bool QNetworkListManagerEvents::start() return true; } -bool QNetworkListManagerEvents::stop() +void QNetworkListManagerEvents::stop() { Q_ASSERT(connectionPoint); auto hr = connectionPoint->Unadvise(cookie); if (FAILED(hr)) { qCWarning(lcNetInfoNLM) << "Failed to unsubscribe from network connectivity events:" << errorStringFromHResult(hr); - return false; + } else { + cookie = 0; } - cookie = 0; + // Even if we fail we should still try to unregister from winrt events: #ifdef SUPPORTS_WINRT - using namespace winrt::Windows::Networking::Connectivity; - // Pass the token we stored earlier to unregister: - NetworkInformation::NetworkStatusChanged(token); - token = {}; + // Try to synchronize unregistering with potentially in-progress callbacks + std::scoped_lock locker(winrtLock); + if (token) { + using namespace winrt::Windows::Networking::Connectivity; + // Pass the token we stored earlier to unregister: + NetworkInformation::NetworkStatusChanged(token); + token = {}; + } #endif - return true; } bool QNetworkListManagerEvents::checkBehindCaptivePortal() diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h index b82d123fa43..67403d55758 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -57,7 +58,7 @@ public: HRESULT STDMETHODCALLTYPE ConnectivityChanged(NLM_CONNECTIVITY newConnectivity) override; [[nodiscard]] bool start(); - bool stop(); + void stop(); [[nodiscard]] bool checkBehindCaptivePortal(); @@ -74,6 +75,7 @@ private: void emitWinRTUpdates(); winrt::event_token token; + QMutex winrtLock; #endif QAtomicInteger ref = 0; diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp index 9673d2cf696..e7d49b4591b 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp @@ -198,7 +198,6 @@ void QNetworkListManagerNetworkInformationBackend::stop() { if (monitoring) { Q_ASSERT(managerEvents); - // Can return false but realistically shouldn't since that would break everything: managerEvents->stop(); monitoring = false; managerEvents.Reset();