diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp index b101a17f9b9..8cb753fc42a 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp @@ -3,6 +3,10 @@ #include "qnetworklistmanagerevents.h" +#include + +#include + #if QT_CONFIG(cpp_winrt) #include #include @@ -102,11 +106,16 @@ bool QNetworkListManagerEvents::start() #if QT_CONFIG(cpp_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: #if QT_CONFIG(cpp_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 9d4d0381036..0224566bce5 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 @@ -53,7 +54,7 @@ public: HRESULT STDMETHODCALLTYPE ConnectivityChanged(NLM_CONNECTIVITY newConnectivity) override; [[nodiscard]] bool start(); - bool stop(); + void stop(); [[nodiscard]] bool checkBehindCaptivePortal(); @@ -70,6 +71,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 f5c5131894b..a5b0179e37c 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp @@ -187,7 +187,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();