From 896acd256dab1367c2ef9176217470b65961e9ed Mon Sep 17 00:00:00 2001 From: sebaszm <45654185+sebaszm@users.noreply.github.com> Date: Fri, 10 Nov 2023 13:44:19 +0100 Subject: [PATCH] [LocationSync] Fix deadlock with OOP plugins (#261) --- LocationSync/LocationService.cpp | 34 ++++++++++++++++------ LocationSync/LocationService.h | 1 + LocationSync/LocationSync.cpp | 43 +++++++++++++++++----------- LocationSync/LocationSyncJsonRpc.cpp | 30 +++++++++++++------ 4 files changed, 74 insertions(+), 34 deletions(-) diff --git a/LocationSync/LocationService.cpp b/LocationSync/LocationService.cpp index 6c9e6b0e..420a9b24 100644 --- a/LocationSync/LocationService.cpp +++ b/LocationSync/LocationService.cpp @@ -488,13 +488,14 @@ POP_WARNING() } else { _publicIPAddress = _infoCarrier->IP(); } - _state = LOADED; + ASSERT(!_publicIPAddress.empty()); Core::NodeId node(_publicIPAddress.c_str(), Core::NodeId::TYPE_UNSPECIFIED); if (node.IsValid() != true) { + _state = FAILED; TRACE(Trace::Information, (_T("Could not determine the external public IP address [%s]"), _publicIPAddress.c_str())); } else { @@ -502,8 +503,7 @@ POP_WARNING() Core::NodeId::ClearIPV6Enabled(); } - TRACE(Trace::Information, (_T("Network connectivity established. Type: %s, on %s"), (node.Type() == Core::NodeId::TYPE_IPV6 ? _T("IPv6") : _T("IPv4")), node.HostAddress().c_str())); - _callback->Dispatch(); + _state = LOADING; } ASSERT(_infoCarrier.IsValid() == true); @@ -543,6 +543,8 @@ POP_WARNING() void LocationService::Dispatch() { uint32_t result = Core::infinite; + bool dispatch = false; + TRACE(Trace::Information, (_T("LocationService: job is dispatched"))); if ((Close(100) != Core::ERROR_NONE) || (IsClosed() == false)) { @@ -561,7 +563,7 @@ POP_WARNING() } } - if ((_state != LOADED) && (_state != FAILED)) { + if ((_state != LOADING) && (_state != LOADED) && (_state != FAILED)) { Core::NodeId remote(_remoteId.c_str(), ((_state == ACTIVE) && (Core::NodeId::IsIPV6Enabled()) ? Core::NodeId::TYPE_IPV6 : Core::NodeId::TYPE_IPV4)); @@ -599,17 +601,31 @@ POP_WARNING() } } - if (_state == FAILED) { + + if (_state == LOADING) { + _state = LOADED; + + Core::NodeId node(_publicIPAddress.c_str(), Core::NodeId::TYPE_UNSPECIFIED); + + TRACE(Trace::Information, (_T("Network connectivity established. Type: %s, on %s"), + (node.Type() == Core::NodeId::TYPE_IPV6 ? _T("IPv6") : _T("IPv4")), node.HostAddress().c_str())); + + dispatch = true; + } + else if (_state == FAILED) { + Core::NodeId::ClearIPV6Enabled(); + + TRACE(Trace::Error, (_T("LocationSync: Network connectivity could *NOT* be established. Falling back to IPv4. %d"), __LINE__)); + _infoCarrier.Release(); + + dispatch = true; } _adminLock.Unlock(); } - if (_state == FAILED) { - Core::NodeId::ClearIPV6Enabled(); - - TRACE(Trace::Error, (_T("LocationSync: Network connectivity could *NOT* be established. Falling back to IPv4. %d"), __LINE__)); + if (dispatch == true) { _callback->Dispatch(); } diff --git a/LocationSync/LocationService.h b/LocationSync/LocationService.h index d11ea71b..8c4fc9ed 100644 --- a/LocationSync/LocationService.h +++ b/LocationSync/LocationService.h @@ -39,6 +39,7 @@ namespace Plugin { ACTIVE, IPV6_INPROGRESS, IPV4_INPROGRESS, + LOADING, LOADED, FAILED }; diff --git a/LocationSync/LocationSync.cpp b/LocationSync/LocationSync.cpp index d30fc0d3..cf17e8a3 100644 --- a/LocationSync/LocationSync.cpp +++ b/LocationSync/LocationSync.cpp @@ -155,24 +155,35 @@ POP_WARNING() Core::ProxyType> response(jsonResponseFactory.Element()); PluginHost::ISubSystem* subSystem = _service->SubSystems(); - ASSERT(subSystem != nullptr); - const PluginHost::ISubSystem::IInternet* internet(subSystem->Get()); - const PluginHost::ISubSystem::ILocation* location(subSystem->Get()); - - if ((internet != nullptr) && (location != nullptr)) { - response->PublicIp = internet->PublicIPAddress(); - response->TimeZone = location->TimeZone(); - response->Region = location->Region(); - response->Country = location->Country(); - response->City = location->City(); - - result->ContentType = Web::MIMETypes::MIME_JSON; - result->Body(Core::ProxyType(response)); - } else { - result->ErrorCode = Web::STATUS_SERVICE_UNAVAILABLE; - result->Message = _T("Internet and Location Service not yet available"); + if (subSystem != nullptr) { + const PluginHost::ISubSystem::IInternet* internet(subSystem->Get()); + + if (internet != nullptr) { + response->PublicIp = internet->PublicIPAddress(); + + const PluginHost::ISubSystem::ILocation* location(subSystem->Get()); + + if (location != nullptr) { + response->TimeZone = location->TimeZone(); + response->Region = location->Region(); + response->Country = location->Country(); + response->City = location->City(); + + location->Release(); + } + + result->ContentType = Web::MIMETypes::MIME_JSON; + result->Body(Core::ProxyType(response)); + + internet->Release(); + } else { + result->ErrorCode = Web::STATUS_SERVICE_UNAVAILABLE; + result->Message = _T("Internet and Location Service not yet available"); + } + + subSystem->Release(); } } else if (request.Verb == Web::Request::HTTP_POST) { index.Next(); diff --git a/LocationSync/LocationSyncJsonRpc.cpp b/LocationSync/LocationSyncJsonRpc.cpp index abcfb82c..f672716d 100644 --- a/LocationSync/LocationSyncJsonRpc.cpp +++ b/LocationSync/LocationSyncJsonRpc.cpp @@ -72,20 +72,32 @@ namespace Plugin { uint32_t LocationSync::get_location(LocationData& response) const { uint32_t status = Core::ERROR_UNAVAILABLE; + PluginHost::ISubSystem* subSystem = _service->SubSystems(); ASSERT(subSystem != nullptr); - const PluginHost::ISubSystem::IInternet* internet(subSystem->Get()); - const PluginHost::ISubSystem::ILocation* location(subSystem->Get()); + if (subSystem != nullptr) { + const PluginHost::ISubSystem::IInternet* internet(subSystem->Get()); + + if (internet != nullptr) { + response.Publicip = internet->PublicIPAddress(); + + const PluginHost::ISubSystem::ILocation* location(subSystem->Get()); + + if (location != nullptr) { + response.Timezone = location->TimeZone(); + response.Region = location->Region(); + response.Country = location->Country(); + response.City = location->City(); + + location->Release(); + } - if ((internet != nullptr) && (location != nullptr)) { - response.Publicip = internet->PublicIPAddress(); + status = Core::ERROR_NONE; + internet->Release(); + } - response.Timezone = location->TimeZone(); - response.Region = location->Region(); - response.Country = location->Country(); - response.City = location->City(); - status = Core::ERROR_NONE; + subSystem->Release(); } return status;