summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuergen Gehring <juergen.gehring@bmw.de>2017-04-07 01:32:39 -0700
committerJuergen Gehring <juergen.gehring@bmw.de>2017-04-07 01:32:39 -0700
commit44103948d4b052603c0b361448ecb4ef7d954f79 (patch)
treef7c95861a4128e0f1cb058eff73ff2911a37f468
parentfad59c73675aea115d0c292b5743de2591bdf6b3 (diff)
downloadgenivi-common-api-dbus-runtime-44103948d4b052603c0b361448ecb4ef7d954f79.tar.gz
CommonAPI-D-Bus 3.1.11.13.1.11.1
-rw-r--r--CHANGES3
-rw-r--r--CMakeLists.txt8
-rw-r--r--include/CommonAPI/DBus/DBusConnection.hpp21
-rw-r--r--include/CommonAPI/DBus/DBusFactory.hpp2
-rw-r--r--include/CommonAPI/DBus/DBusProxyConnection.hpp7
-rw-r--r--src/CommonAPI/DBus/DBusConnection.cpp491
-rw-r--r--src/CommonAPI/DBus/DBusFactory.cpp14
-rw-r--r--src/dbus-patches/capi-dbus-1-pc.patch9
8 files changed, 391 insertions, 164 deletions
diff --git a/CHANGES b/CHANGES
index 46ae22e..7d4b1a0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,8 @@
Changes
=======
+v3.1.11.1
+- Support deployment for anonymous arrays
+- Fixed concurrency problem / segfault in unregisterStub()
v3.1.11
- Fixed availability problem of proxies that connect to legacy managed services by changing the way of resolving object paths and available interfaces
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 350a1ed..b40aa56 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -177,8 +177,12 @@ include_directories(
${DBus_INCLUDE_DIRS}
)
-if ("${USE_INSTALLED_DBUS}" STREQUAL "OFF")
- set (DBus_LIBRARIES dbus-1)
+if ("${USE_INSTALLED_DBUS}" STREQUAL "ON")
+ link_directories(
+ ${DBus_LIBRARY_DIRS}
+ )
+else()
+ set (DBus_LIBRARIES dbus-1)
link_directories(
${DBus_INCLUDE_DIRS}/dbus/.libs
)
diff --git a/include/CommonAPI/DBus/DBusConnection.hpp b/include/CommonAPI/DBus/DBusConnection.hpp
index e88eab6..a382bae 100644
--- a/include/CommonAPI/DBus/DBusConnection.hpp
+++ b/include/CommonAPI/DBus/DBusConnection.hpp
@@ -226,6 +226,7 @@ public:
typedef std::tuple<std::string, std::string, std::string> DBusSignalMatchRuleTuple;
typedef std::pair<uint32_t, std::string> DBusSignalMatchRuleMapping;
typedef std::unordered_map<DBusSignalMatchRuleTuple, DBusSignalMatchRuleMapping> DBusSignalMatchRulesMap;
+ typedef std::unordered_map<std::string, size_t> DBusOMSignalMatchRulesMap;
private:
struct PendingCallNotificationData {
@@ -310,10 +311,13 @@ public:
void deleteAsyncHandlers();
+ uint32_t getNumberOfSignalMemberHandlers(DBusSignalHandlerPath handlerPath);
+
::DBusConnection* connection_;
mutable std::recursive_mutex connectionGuard_;
- std::mutex signalGuard_;
+ std::mutex signalHandlersGuard_;
+
std::mutex objectManagerGuard_;
std::mutex serviceRegistryGuard_;
@@ -325,12 +329,17 @@ public:
DBusSignalMatchRulesMap dbusSignalMatchRulesMap_;
- DBusSignalHandlerTable dbusSignalHandlerTable_;
+ DBusSignalHandlerTable dbusSignalHandlers_;
+ DBusSignalHandlerTable dbusSignalHandlersToAdd_;
+ DBusSignalHandlerTable dbusSignalHandlersToRemove_;
+
+ std::mutex dbusOMSignalHandlersGuard_;
+
+ DBusOMSignalMatchRulesMap dbusOMSignalMatchRulesMap_;
- std::unordered_map<std::string, size_t> dbusObjectManagerSignalMatchRulesMap_;
- std::unordered_multimap<std::string, std::pair<DBusSignalHandler*,
- std::weak_ptr<DBusSignalHandler>>> dbusObjectManagerSignalHandlerTable_;
- std::mutex dbusObjectManagerSignalGuard_;
+ DBusOMSignalHandlerTable dbusOMSignalHandlers_;
+ DBusOMSignalHandlerTable dbusOMSignalHandlersToAdd_;
+ DBusOMSignalHandlerTable dbusOMSignalHandlersToRemove_;
COMMONAPI_EXPORT bool addObjectManagerSignalMatchRule(const std::string& dbusBusName);
COMMONAPI_EXPORT bool removeObjectManagerSignalMatchRule(const std::string& dbusBusName);
diff --git a/include/CommonAPI/DBus/DBusFactory.hpp b/include/CommonAPI/DBus/DBusFactory.hpp
index 157382d..9654a94 100644
--- a/include/CommonAPI/DBus/DBusFactory.hpp
+++ b/include/CommonAPI/DBus/DBusFactory.hpp
@@ -109,7 +109,6 @@ private:
// Managed services
typedef std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> ServicesMap;
- COMMONAPI_EXPORT bool unregisterManagedService(const ServicesMap::iterator &);
private:
static std::shared_ptr<Factory> theFactory;
@@ -121,6 +120,7 @@ private:
std::map<std::string, StubAdapterCreateFunction> stubAdapterCreateFunctions_;
ServicesMap services_;
+ std::recursive_mutex servicesMutex_;
std::list<InterfaceInitFunction> initializers_;
std::mutex initializerMutex_;
diff --git a/include/CommonAPI/DBus/DBusProxyConnection.hpp b/include/CommonAPI/DBus/DBusProxyConnection.hpp
index ec02082..41797e0 100644
--- a/include/CommonAPI/DBus/DBusProxyConnection.hpp
+++ b/include/CommonAPI/DBus/DBusProxyConnection.hpp
@@ -62,9 +62,10 @@ class DBusProxyConnection {
// objectPath, interfaceName, interfaceMemberName, interfaceMemberSignature
typedef std::tuple<std::string, std::string, std::string, std::string> DBusSignalHandlerPath;
typedef std::unordered_map<DBusSignalHandlerPath,
- std::pair<std::shared_ptr<std::recursive_mutex>,
- std::map<DBusSignalHandler*,
- std::weak_ptr<DBusProxyConnection::DBusSignalHandler>>>> DBusSignalHandlerTable;
+ std::map<DBusSignalHandler*,
+ std::weak_ptr<DBusProxyConnection::DBusSignalHandler>>> DBusSignalHandlerTable;
+ typedef std::unordered_multimap<std::string, std::pair<DBusSignalHandler*,
+ std::weak_ptr<DBusSignalHandler>>> DBusOMSignalHandlerTable;
typedef DBusSignalHandlerPath DBusSignalHandlerToken;
class DBusSignalHandler {
diff --git a/src/CommonAPI/DBus/DBusConnection.cpp b/src/CommonAPI/DBus/DBusConnection.cpp
index 589b5f4..0ce70bc 100644
--- a/src/CommonAPI/DBus/DBusConnection.cpp
+++ b/src/CommonAPI/DBus/DBusConnection.cpp
@@ -1143,49 +1143,58 @@ DBusProxyConnection::DBusSignalHandlerToken DBusConnection::addSignalMemberHandl
interfaceMemberName,
interfaceMemberSignature);
- std::unique_lock<std::mutex> dbusSignalLock(signalGuard_);
+ std::lock_guard<std::mutex> dbusSignalHandlersLock(signalHandlersGuard_);
- auto signalEntry = dbusSignalHandlerTable_.find(dbusSignalHandlerPath);
- const bool isFirstSignalMemberHandler = (signalEntry == dbusSignalHandlerTable_.end());
-
- auto itsHandler = dbusSignalHandler.lock();
+ if(auto itsHandler = dbusSignalHandler.lock()) {
- if (itsHandler && isFirstSignalMemberHandler) {
- addLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName, justAddFilter);
+ uint32_t lastNumOfSignalMemberHandlers = getNumberOfSignalMemberHandlers(dbusSignalHandlerPath);
- std::map<DBusSignalHandler*, std::weak_ptr<DBusSignalHandler>> handlerList;
- handlerList[itsHandler.get()] = dbusSignalHandler;
+ //check if signal handler is already added
+ auto signalHandlerPathIt = dbusSignalHandlers_.find(dbusSignalHandlerPath);
+ if(signalHandlerPathIt == dbusSignalHandlers_.end() ||
+ signalHandlerPathIt->second.find(itsHandler.get()) == signalHandlerPathIt->second.end()) {
- dbusSignalHandlerTable_.insert( {
- dbusSignalHandlerPath,
- std::make_pair(std::make_shared<std::recursive_mutex>(), std::move(handlerList))
- } );
- } else if (itsHandler && !isFirstSignalMemberHandler) {
+ // the signal handler is not added yet for the 'dbusSignalHandlerPath' --> needs to be added
+ auto signalHandlerPathToAddIt = dbusSignalHandlersToAdd_.find(dbusSignalHandlerPath);
+ if(signalHandlerPathToAddIt == dbusSignalHandlersToAdd_.end()) {
- //get mutex for signal entry
- auto signalEntryMutex = signalEntry->second.first;
+ // is first signal member handler for this 'dbusSignalHandlerPath' --> add
+ std::map<DBusSignalHandler*, std::weak_ptr<DBusSignalHandler>> handlerList;
+ handlerList[itsHandler.get()] = dbusSignalHandler;
- // mutex of signal entry must be locked first to avoid potential deadlock
- dbusSignalLock.unlock();
- signalEntryMutex->lock();
+ dbusSignalHandlersToAdd_.insert( {
+ dbusSignalHandlerPath,
+ std::move(handlerList)
+ } );
+ } else {
+ // add further signal handler
+ signalHandlerPathToAddIt->second[itsHandler.get()] = dbusSignalHandler;
+ }
- dbusSignalLock.lock();
- signalEntry = dbusSignalHandlerTable_.find(dbusSignalHandlerPath);
- if(signalEntry != dbusSignalHandlerTable_.end()) {
- signalEntry->second.second[itsHandler.get()] = dbusSignalHandler;
} else {
- //is first signal member handler again
- addLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName, justAddFilter);
+ // signal handler is already added
+ // check if handler is going to be removed
+ auto signalHandlerPathToRemoveIt = dbusSignalHandlersToRemove_.find(dbusSignalHandlerPath);
+ if(signalHandlerPathToRemoveIt != dbusSignalHandlersToRemove_.end()) {
+
+ auto handlerToRemoveEntry = signalHandlerPathToRemoveIt->second.find(itsHandler.get());
+ if(handlerToRemoveEntry != signalHandlerPathToRemoveIt->second.end()) {
+
+ // signal handler is going to be removed --> erase
+ signalHandlerPathToRemoveIt->second.erase(handlerToRemoveEntry);
+ if(signalHandlerPathToRemoveIt->second.empty()) {
+ dbusSignalHandlersToRemove_.erase(signalHandlerPathToRemoveIt);
+ }
+ }
+ }
+ }
- std::map<DBusSignalHandler*, std::weak_ptr<DBusSignalHandler>> handlerList;
- handlerList[itsHandler.get()] = dbusSignalHandler;
+ uint32_t numOfSignalMemberHandlers = getNumberOfSignalMemberHandlers(dbusSignalHandlerPath);
- dbusSignalHandlerTable_.insert( {
- dbusSignalHandlerPath,
- std::make_pair(std::make_shared<std::recursive_mutex>(), std::move(handlerList))
- } );
+ if(lastNumOfSignalMemberHandlers == 0 && numOfSignalMemberHandlers == 1) {
+ // a new signal handler for the 'dbusSignalHandlerPath' was added --> add match rule
+ addLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName, justAddFilter);
}
- signalEntryMutex->unlock();
}
return dbusSignalHandlerPath;
@@ -1193,38 +1202,72 @@ DBusProxyConnection::DBusSignalHandlerToken DBusConnection::addSignalMemberHandl
bool DBusConnection::removeSignalMemberHandler(const DBusSignalHandlerToken &dbusSignalHandlerToken,
const DBusSignalHandler* dbusSignalHandler) {
- bool lastHandlerRemoved = false;
- std::unique_lock<std::mutex> itsLock(signalGuard_);
- auto signalEntry = dbusSignalHandlerTable_.find(dbusSignalHandlerToken);
- if (signalEntry != dbusSignalHandlerTable_.end()) {
+ std::lock_guard<std::mutex> itsLock(signalHandlersGuard_);
+
+ uint32_t lastNumOfSignalMemberHandlers = getNumberOfSignalMemberHandlers(dbusSignalHandlerToken);
+
+ //check if signal handler is already added
+ auto signalHandlerPathIt = dbusSignalHandlers_.find(dbusSignalHandlerToken);
+ if(signalHandlerPathIt != dbusSignalHandlers_.end() &&
+ signalHandlerPathIt->second.find(const_cast<DBusSignalHandler*>(dbusSignalHandler)) !=
+ signalHandlerPathIt->second.end()) {
+
+ // signal handler is already added
+ // check if handler is going to be removed
+ auto signalHandlerPathToRemoveIt = dbusSignalHandlersToRemove_.find(dbusSignalHandlerToken);
+ if(signalHandlerPathToRemoveIt != dbusSignalHandlersToRemove_.end()) {
- auto signalEntryMutex = signalEntry->second.first;
+ auto it = signalHandlerPathToRemoveIt->second.find(const_cast<DBusSignalHandler*>(dbusSignalHandler));
- // mutex of signal entry must be locked first to avoid potential deadlock
- itsLock.unlock();
- signalEntryMutex->lock();
+ if(it == signalHandlerPathToRemoveIt->second.end()) {
+
+ // handler is not going to be removed yet --> remove
+ signalHandlerPathToRemoveIt->second[const_cast<DBusSignalHandler*>(dbusSignalHandler)] =
+ std::weak_ptr<DBusSignalHandler>();
+ }
+
+ } else {
+ // handler is not going to be removed yet. No dbus signal handler token found --> insert with handler to remove
+ std::map<DBusSignalHandler*, std::weak_ptr<DBusSignalHandler>> handlerList;
+ handlerList[const_cast<DBusSignalHandler*>(dbusSignalHandler)] =
+ std::weak_ptr<DBusSignalHandler>();
- itsLock.lock();
- signalEntry = dbusSignalHandlerTable_.find(dbusSignalHandlerToken);
- if(signalEntry != dbusSignalHandlerTable_.end()) {
- auto selectedHandler = signalEntry->second.second.find(const_cast<DBusSignalHandler*>(dbusSignalHandler));
- if (selectedHandler != signalEntry->second.second.end()) {
- signalEntry->second.second.erase(selectedHandler);
- lastHandlerRemoved = (signalEntry->second.second.empty());
+ dbusSignalHandlersToRemove_.insert( {
+ dbusSignalHandlerToken,
+ std::move(handlerList)
+ } );
+ }
+
+ } else {
+ // signal handler not added yet
+ // check if handler is going to be added
+ auto signalHandlerPathToAddIt = dbusSignalHandlersToAdd_.find(dbusSignalHandlerToken);
+ if(signalHandlerPathToAddIt != dbusSignalHandlersToAdd_.end()) {
+
+ auto handlersToAddEntry = signalHandlerPathToAddIt->second.find(const_cast<DBusSignalHandler*>(dbusSignalHandler));
+ if(handlersToAddEntry != signalHandlerPathToAddIt->second.end()) {
+
+ // handler is planned to be added --> erase
+ signalHandlerPathToAddIt->second.erase(handlersToAddEntry);
+ if(signalHandlerPathToAddIt->second.empty()) {
+ dbusSignalHandlersToAdd_.erase(signalHandlerPathToAddIt);
+ }
}
}
- signalEntryMutex->unlock();
}
- if (lastHandlerRemoved) {
- dbusSignalHandlerTable_.erase(signalEntry);
+ uint32_t numOfSignalMemberHandlers = getNumberOfSignalMemberHandlers(dbusSignalHandlerToken);
+
+ if(lastNumOfSignalMemberHandlers == 1 && numOfSignalMemberHandlers == 0) {
+ // the last signal handler for the 'dbusSignalHandlerToken' was removed --> remove match rule
removeLibdbusSignalMatchRule(std::get<0>(dbusSignalHandlerToken),
- std::get<1>(dbusSignalHandlerToken),
- std::get<2>(dbusSignalHandlerToken));
+ std::get<1>(dbusSignalHandlerToken),
+ std::get<2>(dbusSignalHandlerToken));
+ return true;
}
- return lastHandlerRemoved;
+ return false;
}
bool DBusConnection::addObjectManagerSignalMemberHandler(const std::string& dbusBusName,
@@ -1234,37 +1277,46 @@ bool DBusConnection::addObjectManagerSignalMemberHandler(const std::string& dbus
}
if(auto itsHandler = dbusSignalHandler.lock()) {
- std::lock_guard<std::mutex> dbusSignalLock(dbusObjectManagerSignalGuard_);
+ std::lock_guard<std::mutex> dbusSignalLock(dbusOMSignalHandlersGuard_);
- auto dbusSignalMatchRuleIterator = dbusObjectManagerSignalMatchRulesMap_.find(dbusBusName);
- const bool isDBusSignalMatchRuleFound = (dbusSignalMatchRuleIterator != dbusObjectManagerSignalMatchRulesMap_.end());
+ auto signalHandlerPathIt = dbusOMSignalHandlers_.find(dbusBusName);
+ if(signalHandlerPathIt == dbusOMSignalHandlers_.end()) {
- if (!isDBusSignalMatchRuleFound) {
- if (isConnected() && !addObjectManagerSignalMatchRule(dbusBusName)) {
- return false;
- }
+ // the signal handler is not added yet --> add
+ auto signalHandlerPathToAddIt = dbusOMSignalHandlersToAdd_.find(dbusBusName);
+ if(signalHandlerPathToAddIt == dbusOMSignalHandlersToAdd_.end()) {
- auto insertResult = dbusObjectManagerSignalMatchRulesMap_.insert({ dbusBusName, 0 });
- const bool isInsertSuccessful = insertResult.second;
+ // is first signal member handler --> add to list and add match rule
+ std::pair<DBusSignalHandler*, std::weak_ptr<DBusSignalHandler>> handler =
+ std::make_pair(itsHandler.get(), dbusSignalHandler);
- if (!isInsertSuccessful) {
- if (isConnected()) {
- const bool isRemoveSignalMatchRuleSuccessful = removeObjectManagerSignalMatchRule(dbusBusName);
- if (!isRemoveSignalMatchRuleSuccessful) {
- COMMONAPI_ERROR(std::string(__FUNCTION__), " removeObjectManagerSignalMatchRule", dbusBusName, " failed");
- }
+ dbusOMSignalHandlersToAdd_.insert( {
+ dbusBusName,
+ std::move(handler)
+ } );
+
+ if (!addObjectManagerSignalMatchRule(dbusBusName)) {
+ return false;
+ }
+ } else {
+ // signal handler is already going to be added
+ COMMONAPI_WARNING(std::string(__FUNCTION__), " a signal handler is already added for ", dbusBusName);
+ return true;
+ }
+ } else {
+ // signal handler is added
+ // check if handler is going to be removed
+ auto signalHandlerPathToRemoveIt= dbusOMSignalHandlersToRemove_.find(dbusBusName);
+ if(signalHandlerPathToRemoveIt != dbusOMSignalHandlersToRemove_.end()) {
+
+ // signal handler is going to be removed --> erase
+ dbusOMSignalHandlersToRemove_.erase(signalHandlerPathToRemoveIt);
+ if(isConnected() && !addObjectManagerSignalMatchRule(dbusBusName)) {
+ return false;
}
- return false;
}
-
- dbusSignalMatchRuleIterator = insertResult.first;
}
-
- size_t &dbusSignalMatchRuleReferenceCount = dbusSignalMatchRuleIterator->second;
- dbusSignalMatchRuleReferenceCount++;
- dbusObjectManagerSignalHandlerTable_.insert( { dbusBusName, std::make_pair(itsHandler.get(), dbusSignalHandler) } );
}
-
return true;
}
@@ -1275,53 +1327,93 @@ bool DBusConnection::removeObjectManagerSignalMemberHandler(const std::string& d
return false;
}
- std::lock_guard<std::mutex> dbusSignalLock(dbusObjectManagerSignalGuard_);
+ std::lock_guard<std::mutex> itsLock(signalHandlersGuard_);
- auto dbusSignalMatchRuleIterator = dbusObjectManagerSignalMatchRulesMap_.find(dbusBusName);
- const bool isDBusSignalMatchRuleFound = (dbusSignalMatchRuleIterator != dbusObjectManagerSignalMatchRulesMap_.end());
+ auto signalHandlerPathIt = dbusOMSignalHandlers_.find(dbusBusName);
+ if(signalHandlerPathIt != dbusOMSignalHandlers_.end()) {
- if (!isDBusSignalMatchRuleFound) {
- return true;
- }
+ // signal handler is added
+ // check if handler is already going to be removed
+ auto signalHandlerPathToRemoveIt = dbusOMSignalHandlersToRemove_.find(dbusBusName);
+ if(signalHandlerPathToRemoveIt != dbusOMSignalHandlersToRemove_.end()) {
- auto dbusObjectManagerSignalHandlerRange = dbusObjectManagerSignalHandlerTable_.equal_range(dbusBusName);
- auto dbusObjectManagerSignalHandlerIterator = std::find_if(
- dbusObjectManagerSignalHandlerRange.first,
- dbusObjectManagerSignalHandlerRange.second,
- [&](decltype(*dbusObjectManagerSignalHandlerRange.first)& it) { return it.second.first == dbusSignalHandler; });
- const bool isDBusSignalHandlerFound = (dbusObjectManagerSignalHandlerIterator != dbusObjectManagerSignalHandlerRange.second);
- if (!isDBusSignalHandlerFound) {
- return false;
- }
+ if(signalHandlerPathToRemoveIt->second.first == dbusSignalHandler) {
+ COMMONAPI_WARNING(std::string(__FUNCTION__), " the signal handler is already removed for ", dbusBusName);
+ return true;
+ } else {
+ COMMONAPI_ERROR(std::string(__FUNCTION__), " the signal handler is not found for ", dbusBusName);
+ return false;
+ }
+ } else {
+ // no dbus signal handler found for 'dbusBusName' --> insert with handler
+ std::pair<DBusSignalHandler*, std::weak_ptr<DBusSignalHandler>> handler =
+ std::make_pair(dbusSignalHandler, std::weak_ptr<DBusSignalHandler>());
- size_t& dbusSignalMatchRuleReferenceCount = dbusSignalMatchRuleIterator->second;
+ dbusOMSignalHandlersToRemove_.insert( {
+ dbusBusName,
+ std::move(handler)
+ } );
- if (0 == dbusSignalMatchRuleReferenceCount) {
- COMMONAPI_ERROR(std::string(__FUNCTION__), "ref count == 0");
+ if (isConnected() && !removeObjectManagerSignalMatchRule(dbusBusName)) {
+ return false;
+ }
+ }
} else {
- dbusSignalMatchRuleReferenceCount--;
- }
-
- const bool isLastDBusSignalMatchRuleReference = (dbusSignalMatchRuleReferenceCount == 0);
- if (isLastDBusSignalMatchRuleReference) {
- if (isConnected() && !removeObjectManagerSignalMatchRule(dbusBusName)) {
- return false;
+ // signal handler not added
+ // check if handler is going to be added
+ auto signalHandlerPathToAddIt = dbusOMSignalHandlersToAdd_.find(dbusBusName);
+ if(signalHandlerPathToAddIt != dbusOMSignalHandlersToAdd_.end()) {
+
+ if(signalHandlerPathToAddIt->second.first == dbusSignalHandler) {
+ // handler is planned to be added --> erase
+ dbusOMSignalHandlersToAdd_.erase(signalHandlerPathToAddIt);
+ if (isConnected() && !removeObjectManagerSignalMatchRule(dbusBusName)) {
+ return false;
+ }
+ } else {
+ COMMONAPI_ERROR(std::string(__FUNCTION__), " the signal handler is not found for ", dbusBusName);
+ return false;
+ }
}
-
- dbusObjectManagerSignalMatchRulesMap_.erase(dbusSignalMatchRuleIterator);
}
-
- dbusObjectManagerSignalHandlerTable_.erase(dbusObjectManagerSignalHandlerIterator);
-
return true;
}
bool DBusConnection::addObjectManagerSignalMatchRule(const std::string& dbusBusName) {
+
std::ostringstream dbusMatchRuleStringStream;
dbusMatchRuleStringStream << "type='signal'"
<< ",sender='" << dbusBusName << "'"
<< ",interface='org.freedesktop.DBus.ObjectManager'";
- return addLibdbusSignalMatchRule(dbusMatchRuleStringStream.str());
+
+ auto dbusSignalMatchRuleIterator = dbusOMSignalMatchRulesMap_.find(dbusBusName);
+ const bool isDBusSignalMatchRuleFound = (dbusSignalMatchRuleIterator != dbusOMSignalMatchRulesMap_.end());
+
+ if (!isDBusSignalMatchRuleFound) {
+
+ if(isConnected() && !addLibdbusSignalMatchRule(dbusMatchRuleStringStream.str())) {
+ return false;
+ }
+
+ auto insertResult = dbusOMSignalMatchRulesMap_.insert({ dbusBusName, 0 });
+ const bool isInsertSuccessful = insertResult.second;
+
+ if (!isInsertSuccessful) {
+ if (isConnected()) {
+ if (!removeObjectManagerSignalMatchRule(dbusBusName)) {
+ COMMONAPI_ERROR(std::string(__FUNCTION__), " removeObjectManagerSignalMatchRule", dbusBusName, " failed");
+ }
+ }
+ return false;
+ }
+
+ dbusSignalMatchRuleIterator = insertResult.first;
+ }
+
+ size_t &dbusSignalMatchRuleReferenceCount = dbusSignalMatchRuleIterator->second;
+ dbusSignalMatchRuleReferenceCount++;
+
+ return true;
}
bool DBusConnection::removeObjectManagerSignalMatchRule(const std::string& dbusBusName) {
@@ -1329,7 +1421,30 @@ bool DBusConnection::removeObjectManagerSignalMatchRule(const std::string& dbusB
dbusMatchRuleStringStream << "type='signal'"
<< ",sender='" << dbusBusName << "'"
<< ",interface='org.freedesktop.DBus.ObjectManager'";
- return removeLibdbusSignalMatchRule(dbusMatchRuleStringStream.str());
+
+ auto dbusSignalMatchRuleIterator = dbusOMSignalMatchRulesMap_.find(dbusBusName);
+ const bool isDBusSignalMatchRuleFound = (dbusSignalMatchRuleIterator != dbusOMSignalMatchRulesMap_.end());
+
+ if (!isDBusSignalMatchRuleFound) {
+ return true;
+ }
+
+ size_t& dbusSignalMatchRuleReferenceCount = dbusSignalMatchRuleIterator->second;
+
+ if (0 == dbusSignalMatchRuleReferenceCount) {
+ COMMONAPI_ERROR(std::string(__FUNCTION__), "ref count == 0");
+ } else {
+ dbusSignalMatchRuleReferenceCount--;
+ }
+
+ const bool isLastDBusSignalMatchRuleReference = (dbusSignalMatchRuleReferenceCount == 0);
+ if (isLastDBusSignalMatchRuleReference) {
+ if (isConnected() && !removeLibdbusSignalMatchRule(dbusBusName)) {
+ return false;
+ }
+ dbusOMSignalMatchRulesMap_.erase(dbusSignalMatchRuleIterator);
+ }
+ return true;
}
/**
@@ -1607,7 +1722,7 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() {
}
// object manager match rules (see DBusServiceRegistry)
- for (const auto& dbusObjectManagerSignalMatchRuleIterator : dbusObjectManagerSignalMatchRulesMap_) {
+ for (const auto& dbusObjectManagerSignalMatchRuleIterator : dbusOMSignalMatchRulesMap_) {
const std::string& dbusBusName = dbusObjectManagerSignalMatchRuleIterator.first;
const bool libdbusSuccess = addObjectManagerSignalMatchRule(dbusBusName);
if (!libdbusSuccess) {
@@ -1634,44 +1749,72 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() {
void DBusConnection::notifyDBusSignalHandlers(DBusSignalHandlerPath handlerPath,
const DBusMessage& dbusMessage,
::DBusHandlerResult& dbusHandlerResult) {
-
- // mutex of signal entry must be locked first to avoid potential deadlock
- DBusSignalHandlerTable::iterator signalEntry;
- bool entryFound = false;
- std::shared_ptr<std::recursive_mutex> signalEntryMutex;
{
- std::lock_guard<std::mutex> itsLock(signalGuard_);
- signalEntry = dbusSignalHandlerTable_.find(handlerPath);
+ std::lock_guard<std::mutex> dbusSignalHandlersLock(signalHandlersGuard_);
- if(signalEntry != dbusSignalHandlerTable_.end()) {
- signalEntryMutex = signalEntry->second.first;
- entryFound = true;
+ // remove signal handlers
+ auto signalHandlerPathToRemoveIt = dbusSignalHandlersToRemove_.find(handlerPath);
+ if(signalHandlerPathToRemoveIt != dbusSignalHandlersToRemove_.end()) {
+
+ for(auto handlerToRemoveIt = signalHandlerPathToRemoveIt->second.begin();
+ handlerToRemoveIt != signalHandlerPathToRemoveIt->second.end();
+ ++handlerToRemoveIt) {
+
+ auto signalHandlerPathIt = dbusSignalHandlers_.find(handlerPath);
+ if(signalHandlerPathIt != dbusSignalHandlers_.end()) {
+ auto signalHandlerIt = signalHandlerPathIt->second.find(handlerToRemoveIt->first);
+ if(signalHandlerIt != signalHandlerPathIt->second.end()) {
+ signalHandlerPathIt->second.erase(signalHandlerIt);
+ }
+ }
+ }
+ auto signalHandlerPathIt = dbusSignalHandlers_.find(handlerPath);
+ if(signalHandlerPathIt != dbusSignalHandlers_.end() &&
+ signalHandlerPathIt->second.empty()) {
+ dbusSignalHandlers_.erase(handlerPath);
+ }
+ dbusSignalHandlersToRemove_.erase(signalHandlerPathToRemoveIt);
}
- }
- if(entryFound) {
- signalEntryMutex->lock();
- std::lock_guard<std::mutex> itsLock(signalGuard_);
- signalEntry = dbusSignalHandlerTable_.find(handlerPath);
+ // add signal handlers
+ auto signalHandlerPathToAddIt = dbusSignalHandlersToAdd_.find(handlerPath);
+ if(signalHandlerPathToAddIt != dbusSignalHandlersToAdd_.end()) {
+
+ for(auto handlerToAddIt = signalHandlerPathToAddIt->second.begin();
+ handlerToAddIt != signalHandlerPathToAddIt->second.end();
+ ++handlerToAddIt) {
+
+ auto signalHandlerPathIt = dbusSignalHandlers_.find(handlerPath);
+ if(signalHandlerPathIt == dbusSignalHandlers_.end()) {
+
+ std::map<DBusSignalHandler*, std::weak_ptr<DBusSignalHandler>> handlerList;
+ handlerList[handlerToAddIt->first] = handlerToAddIt->second;
+
+ dbusSignalHandlers_.insert( {
+ handlerPath,
+ std::move(handlerList)
+ } );
+ } else {
+ signalHandlerPathIt->second[handlerToAddIt->first] = handlerToAddIt->second;
+ }
+ }
+ dbusSignalHandlersToAdd_.erase(signalHandlerPathToAddIt);
+ }
}
// ensure, the registry survives
std::shared_ptr<DBusServiceRegistry> itsRegistry_ = DBusServiceRegistry::get(shared_from_this());
- if(entryFound &&
- signalEntry != dbusSignalHandlerTable_.end() &&
- !signalEntry->second.second.empty()) {
-
- // copy signal handlers
- auto dbusSignalhandlers = signalEntry->second.second;
- signalEntryMutex->unlock();
-
- auto handlerEntry = dbusSignalhandlers.begin();
- while (handlerEntry != dbusSignalhandlers.end()) {
- std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler = handlerEntry->second;
- if(auto itsHandler = dbusSignalHandler.lock())
+ // notify
+ auto signalHandlerPathIt = dbusSignalHandlers_.find(handlerPath);
+ if(signalHandlerPathIt != dbusSignalHandlers_.end()) {
+ for(auto handlerIt = signalHandlerPathIt->second.begin();
+ handlerIt != signalHandlerPathIt->second.end();
+ ++handlerIt) {
+ std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler = handlerIt->second;
+ if(auto itsHandler = dbusSignalHandler.lock()) {
itsHandler->onSignalDBusMessage(dbusMessage);
- handlerEntry++;
+ }
}
}
dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED;
@@ -1680,23 +1823,63 @@ void DBusConnection::notifyDBusSignalHandlers(DBusSignalHandlerPath handlerPath,
void DBusConnection::notifyDBusOMSignalHandlers(const char* dbusSenderName,
const DBusMessage& dbusMessage,
::DBusHandlerResult& dbusHandlerResult) {
- std::vector<std::weak_ptr<DBusProxyConnection::DBusSignalHandler>> dbusOMSignalHandlers;
{
- std::lock_guard<std::mutex> itsLock(dbusObjectManagerSignalGuard_);
- auto equalRange = dbusObjectManagerSignalHandlerTable_.equal_range(dbusSenderName);
+ std::lock_guard<std::mutex> dbusOMSignalHandlersLock(dbusOMSignalHandlersGuard_);
+
+ // remove signal handlers
+ auto signalHandlerPathToRemoveIt = dbusOMSignalHandlersToRemove_.find(dbusSenderName);
+ if(signalHandlerPathToRemoveIt != dbusOMSignalHandlersToRemove_.end()) {
- if (equalRange.first != equalRange.second) {
- dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED;
+ auto signalHandlerPathIt = dbusOMSignalHandlers_.find(dbusSenderName);
+ if(signalHandlerPathIt != dbusOMSignalHandlers_.end()) {
+
+ if(signalHandlerPathToRemoveIt->second.first ==
+ signalHandlerPathIt->second.first) {
+ dbusOMSignalHandlers_.erase(signalHandlerPathIt);
+ dbusOMSignalHandlersToRemove_.erase(signalHandlerPathToRemoveIt);
+ } else {
+ COMMONAPI_ERROR(std::string(__FUNCTION__), " signal handler can not be removed ", dbusSenderName);
+ return;
+ }
+ }
}
- while (equalRange.first != equalRange.second) {
- dbusOMSignalHandlers.push_back(equalRange.first->second.second);
- equalRange.first++;
+
+ // add signal handlers
+ auto signalHandlerPathToAddIt = dbusOMSignalHandlersToAdd_.find(dbusSenderName);
+ if(signalHandlerPathToAddIt != dbusOMSignalHandlersToAdd_.end()) {
+
+ auto signalHandlerPathIt = dbusOMSignalHandlers_.find(dbusSenderName);
+ if(signalHandlerPathIt == dbusOMSignalHandlers_.end()) {
+
+ dbusOMSignalHandlers_.insert( {
+ dbusSenderName,
+ std::move(signalHandlerPathToAddIt->second)
+ } );
+
+ } else {
+ if(signalHandlerPathToAddIt->second.first ==
+ signalHandlerPathIt->second.first) {
+ COMMONAPI_ERROR(std::string(__FUNCTION__), " signal handler already added for ", dbusSenderName);
+ return;
+ } else {
+ COMMONAPI_ERROR(std::string(__FUNCTION__), " signal handler is trying to be added but "
+ "a signal handler is already added for", dbusSenderName);
+ return;
+ }
+ }
+ dbusOMSignalHandlersToAdd_.erase(signalHandlerPathToAddIt);
}
}
- for(auto it = dbusOMSignalHandlers.begin(); it != dbusOMSignalHandlers.end(); ++it) {
- if(auto itsHandler = it->lock())
+ dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED;
+
+ // notify
+ auto signalHandlerPathIt = dbusOMSignalHandlers_.find(dbusSenderName);
+ if(signalHandlerPathIt != dbusOMSignalHandlers_.end()) {
+ std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler = signalHandlerPathIt->second.second;
+ if(auto itsHandler = dbusSignalHandler.lock()) {
itsHandler->onSignalDBusMessage(dbusMessage);
+ }
}
}
@@ -1844,5 +2027,19 @@ void DBusConnection::deleteAsyncHandlers() {
}
}
+uint32_t DBusConnection::getNumberOfSignalMemberHandlers(DBusSignalHandlerPath handlerPath) {
+ uint32_t handlers, handlersToAdd, handlersToRemove;
+
+ auto signalHandlerPathIt = dbusSignalHandlers_.find(handlerPath);
+ auto signalHandlerPathToAddIt = dbusSignalHandlersToAdd_.find(handlerPath);
+ auto signalHandlerPathToRemoveIt = dbusSignalHandlersToRemove_.find(handlerPath);
+
+ (signalHandlerPathIt != dbusSignalHandlers_.end()) ? handlers = (uint32_t)signalHandlerPathIt->second.size() : handlers = 0;
+ (signalHandlerPathToAddIt != dbusSignalHandlersToAdd_.end()) ? handlersToAdd = (uint32_t)signalHandlerPathToAddIt->second.size() : handlersToAdd = 0;
+ (signalHandlerPathToRemoveIt != dbusSignalHandlersToRemove_.end()) ? handlersToRemove = (uint32_t)signalHandlerPathToRemoveIt->second.size() : handlersToRemove = 0;
+
+ return handlers - handlersToRemove + handlersToAdd;
+}
+
} // namespace DBus
} // namespace CommonAPI
diff --git a/src/CommonAPI/DBus/DBusFactory.cpp b/src/CommonAPI/DBus/DBusFactory.cpp
index 99f7e8e..0d10c61 100644
--- a/src/CommonAPI/DBus/DBusFactory.cpp
+++ b/src/CommonAPI/DBus/DBusFactory.cpp
@@ -182,6 +182,7 @@ Factory::registerStub(
bool
Factory::unregisterStub(const std::string &_domain, const std::string &_interface, const std::string &_instance) {
CommonAPI::Address address(_domain, _interface, _instance);
+ std::unique_lock<std::recursive_mutex> itsLock(servicesMutex_);
const auto &adapterResult = services_.find(address.getAddress());
if (adapterResult != services_.end()) {
const auto _adapter = adapterResult->second;
@@ -202,6 +203,8 @@ Factory::unregisterStub(const std::string &_domain, const std::string &_interfac
services_.erase(adapterResult->first);
+ itsLock.unlock();
+
decrementConnection(connection);
return true;
@@ -215,6 +218,7 @@ Factory::registerStubAdapter(std::shared_ptr<DBusStubAdapter> _adapter) {
CommonAPI::Address address;
DBusAddress dbusAddress = _adapter->getDBusAddress();
if (DBusAddressTranslator::get()->translate(dbusAddress, address)) {
+ std::lock_guard<std::recursive_mutex> itsLock(servicesMutex_);
const auto &insertResult = services_.insert( { address.getAddress(), _adapter } );
const auto &connection = _adapter->getDBusConnection();
@@ -338,6 +342,7 @@ Factory::getConnection(std::shared_ptr<MainLoopContext> _context) {
///////////////////////////////////////////////////////////////////////////////
std::shared_ptr<DBusStubAdapter>
Factory::getRegisteredService(const std::string &_address) {
+ std::lock_guard<std::recursive_mutex> itsLock(servicesMutex_);
auto serviceIterator = services_.find(_address);
if (serviceIterator != services_.end()) {
return serviceIterator->second;
@@ -370,6 +375,7 @@ bool
Factory::registerManagedService(const std::shared_ptr<DBusStubAdapter> &_stubAdapter) {
auto itsAddress = _stubAdapter->getAddress().getAddress();
+ std::lock_guard<std::recursive_mutex> itsLock(servicesMutex_);
const auto &insertResult = services_.insert( { itsAddress, _stubAdapter} );
if (insertResult.second) {
const auto &connection = _stubAdapter->getDBusConnection();
@@ -401,11 +407,8 @@ Factory::registerManagedService(const std::shared_ptr<DBusStubAdapter> &_stubAda
bool
Factory::unregisterManagedService(const std::string &_address) {
- return unregisterManagedService(services_.find(_address));
-}
-
-bool
-Factory::unregisterManagedService(const ServicesMap::iterator &iterator) {
+ std::unique_lock<std::recursive_mutex> itsLock(servicesMutex_);
+ const ServicesMap::iterator iterator = services_.find(_address);
if (iterator == services_.end())
return true;
@@ -419,6 +422,7 @@ Factory::unregisterManagedService(const ServicesMap::iterator &iterator) {
if (isUnregistered) {
connection->releaseServiceName(serviceName);
services_.erase(iterator);
+ itsLock.unlock();
decrementConnection(connection);
}
// TODO: log error
diff --git a/src/dbus-patches/capi-dbus-1-pc.patch b/src/dbus-patches/capi-dbus-1-pc.patch
new file mode 100644
index 0000000..c49a791
--- /dev/null
+++ b/src/dbus-patches/capi-dbus-1-pc.patch
@@ -0,0 +1,9 @@
+diff --git a/dbus-1.pc.in b/dbus-1.pc.in
+index f93d156..2e137cf 100644
+--- a/dbus-1.pc.in
++++ b/dbus-1.pc.in
+@@ -18,3 +18,4 @@ Version: @VERSION@
+ Libs: -L${libdir} -ldbus-1
+ Libs.private: @LIBDBUS_LIBS@
+ Cflags: -I${includedir}/dbus-1.0 -I${libdir}/dbus-1.0/include @DBUS_STATIC_BUILD_CPPFLAGS@
++Ldflags: -L${libdir}