| From 13a4169b5ecb1f742de03edafd52954995d879f1 Mon Sep 17 00:00:00 2001 |
| From: Pierre Wielders <pierre@wielders.net> |
| Date: Mon, 24 Oct 2022 17:41:29 +0200 |
| Subject: [PATCH] [SERVICES] Starting multiples services concurrently might |
| crash the system due to concurrent access to the std::list<>. |
| |
| --- |
| Source/core/Services.cpp | 28 +++++++++++++++++++++------- |
| 1 file changed, 21 insertions(+), 7 deletions(-) |
| |
| diff --git a/Source/core/Services.cpp b/Source/core/Services.cpp |
| index 1aed2d0e..e192ffdd 100644 |
| --- a/Source/core/Services.cpp |
| +++ b/Source/core/Services.cpp |
| @@ -38,20 +38,28 @@ namespace Core { |
| |
| void ServiceAdministrator::Register(IServiceMetadata* metadata, IServiceFactory* factory) |
| { |
| + _adminLock.Lock(); |
| + |
| // Only register a service once !!! |
| ASSERT(std::find(_services.begin(), _services.end(), ServiceBlock(metadata, factory)) == _services.end()); |
| |
| _services.emplace_back(metadata, factory); |
| + |
| + _adminLock.Unlock(); |
| } |
| |
| void ServiceAdministrator::Unregister(IServiceMetadata* metadata, IServiceFactory* factory) |
| { |
| + _adminLock.Lock(); |
| + |
| ServiceList::iterator index = std::find(_services.begin(), _services.end(), ServiceBlock(metadata, factory)); |
| |
| // Only unregister a service once !!! |
| ASSERT(index != _services.end()); |
| |
| _services.erase(index); |
| + |
| + _adminLock.Unlock(); |
| } |
| |
| /* static */ ServiceAdministrator& ServiceAdministrator::Instance() |
| @@ -61,23 +69,29 @@ namespace Core { |
| |
| void* ServiceAdministrator::Instantiate(const Library& library, const char name[], const uint32_t version, const uint32_t interfaceNumber) |
| { |
| - bool found = false; |
| + void* result = nullptr; |
| + |
| + _adminLock.Lock(); |
| + |
| ServiceList::iterator index = _services.begin(); |
| |
| - while ((index != _services.end()) && (found == false)) { |
| + while ((index != _services.end()) && (result == nullptr)) { |
| const char* thisName = index->first->ServiceName().c_str(); |
| - found = ((strcmp(thisName, name) == 0) && ((version == static_cast<uint32_t>(~0)) || (version == ((index->first->Major() << 8) | index->first->Minor())))); |
| - |
| - if (found == false) { |
| + if ((strcmp(thisName, name) == 0) && ((version == static_cast<uint32_t>(~0)) || (version == ((index->first->Major() << 8) | index->first->Minor())))) { |
| + result = index->second->Create(index->first, library, interfaceNumber); |
| + } |
| + else { |
| index++; |
| } |
| } |
| |
| - if(found == false){ |
| + _adminLock.Unlock(); |
| + |
| + if(result == nullptr){ |
| TRACE_L1("Missing implementation classname %s in library %s\n", name, library.Name().c_str()); |
| } |
| |
| - return (found == true ? index->second->Create(index->first, library, interfaceNumber) : nullptr); |
| + return (result); |
| } |
| |
| void ServiceAdministrator::ReleaseLibrary(Library& reference) |
| -- |
| 2.34.1 |
| |