diff options
Diffstat (limited to 'src')
29 files changed, 472 insertions, 328 deletions
diff --git a/src/CommonAPI/DBus/DBusAddress.cpp b/src/CommonAPI/DBus/DBusAddress.cpp index d73cfc0..4819a40 100644 --- a/src/CommonAPI/DBus/DBusAddress.cpp +++ b/src/CommonAPI/DBus/DBusAddress.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusAddressTranslator.cpp b/src/CommonAPI/DBus/DBusAddressTranslator.cpp index 460ab16..49f42d4 100644 --- a/src/CommonAPI/DBus/DBusAddressTranslator.cpp +++ b/src/CommonAPI/DBus/DBusAddressTranslator.cpp @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifdef WIN32 +#ifdef _WIN32 #include <Windows.h> #else #include <unistd.h> @@ -223,7 +223,7 @@ DBusAddressTranslator::readConfiguration() { #define MAX_PATH_LEN 255 std::string config; char currentDirectory[MAX_PATH_LEN]; -#ifdef WIN32 +#ifdef _WIN32 if (GetCurrentDirectory(MAX_PATH_LEN, currentDirectory)) { #else if (getcwd(currentDirectory, MAX_PATH_LEN)) { diff --git a/src/CommonAPI/DBus/DBusClientId.cpp b/src/CommonAPI/DBus/DBusClientId.cpp index 7c9f195..12983b5 100644 --- a/src/CommonAPI/DBus/DBusClientId.cpp +++ b/src/CommonAPI/DBus/DBusClientId.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusConnection.cpp b/src/CommonAPI/DBus/DBusConnection.cpp index 3ed06a7..589b5f4 100644 --- a/src/CommonAPI/DBus/DBusConnection.cpp +++ b/src/CommonAPI/DBus/DBusConnection.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -498,11 +498,10 @@ DBusProxyConnection::ConnectionStatusEvent& DBusConnection::getConnectionStatusE //Does this need to be a weak pointer? const std::shared_ptr<DBusObjectManager> DBusConnection::getDBusObjectManager() { if (!dbusObjectManager_) { - objectManagerGuard_.lock(); + std::lock_guard<std::mutex> itsLock(objectManagerGuard_); if (!dbusObjectManager_) { dbusObjectManager_ = std::make_shared<DBusObjectManager>(shared_from_this()); } - objectManagerGuard_.unlock(); } return dbusObjectManager_; } @@ -656,140 +655,163 @@ void DBusConnection::onLibdbusDataCleanup(void *_data) { } //Would not be needed if libdbus would actually handle its timeouts for pending calls. -void DBusConnection::enforceAsynchronousTimeouts() const { - std::unique_lock<std::recursive_mutex> itsLock(enforcerThreadMutex_); - - while (!enforcerThreadCancelled_) { - enforceTimeoutMutex_.lock(); +void DBusConnection::enforceAsynchronousTimeouts() { + { + std::unique_lock<std::recursive_mutex> itsLock(enforcerThreadMutex_); - int timeout = std::numeric_limits<int>::max(); // not really, but nearly "forever" - if (timeoutMap_.size() > 0) { - auto minTimeoutElement = std::min_element(timeoutMap_.begin(), timeoutMap_.end(), - [] (const TimeoutMapElement& lhs, const TimeoutMapElement& rhs) { - return std::get<0>(lhs.second) < std::get<0>(rhs.second); - }); + while (!enforcerThreadCancelled_) { - auto minTimeout = std::get<0>(minTimeoutElement->second); + int timeout = std::numeric_limits<int>::max(); // not really, but nearly "forever" + { + std::lock_guard<std::mutex> itsLock(enforceTimeoutMutex_); + if (timeoutMap_.size() > 0) { + auto minTimeoutElement = std::min_element(timeoutMap_.begin(), timeoutMap_.end(), + [] (const TimeoutMapElement& lhs, const TimeoutMapElement& rhs) { + return std::get<0>(lhs.second) < std::get<0>(rhs.second); + }); - std::chrono::steady_clock::time_point now = (std::chrono::steady_clock::time_point) std::chrono::steady_clock::now(); + auto minTimeout = std::get<0>(minTimeoutElement->second); - timeout = (int)std::chrono::duration_cast<std::chrono::milliseconds>(minTimeout - now).count(); - } + std::chrono::steady_clock::time_point now = (std::chrono::steady_clock::time_point) std::chrono::steady_clock::now(); - enforceTimeoutMutex_.unlock(); + timeout = (int)std::chrono::duration_cast<std::chrono::milliseconds>(minTimeout - now).count(); + } + } - if (std::cv_status::timeout == - enforceTimeoutCondition_.wait_for(itsLock, std::chrono::milliseconds(timeout))) { + if (std::cv_status::timeout == + enforceTimeoutCondition_.wait_for(itsLock, std::chrono::milliseconds(timeout))) { - //Do not access members if the DBusConnection was destroyed during the unlocked phase. - enforceTimeoutMutex_.lock(); - auto it = timeoutMap_.begin(); - while (it != timeoutMap_.end()) { - std::chrono::steady_clock::time_point now = (std::chrono::steady_clock::time_point) std::chrono::steady_clock::now(); + //Do not access members if the DBusConnection was destroyed during the unlocked phase. + std::lock_guard<std::mutex> itsLock(enforceTimeoutMutex_); + auto it = timeoutMap_.begin(); + while (it != timeoutMap_.end()) { + std::chrono::steady_clock::time_point now = (std::chrono::steady_clock::time_point) std::chrono::steady_clock::now(); - DBusMessageReplyAsyncHandler* asyncHandler = std::get<1>(it->second); - DBusPendingCall* libdbusPendingCall = it->first; + DBusMessageReplyAsyncHandler* asyncHandler = std::get<1>(it->second); + DBusPendingCall* libdbusPendingCall = it->first; - if (now > std::get<0>(it->second)) { + if (now > std::get<0>(it->second)) { - asyncHandler->lock(); - bool executionStarted = asyncHandler->getExecutionStarted(); - bool executionFinished = asyncHandler->getExecutionFinished(); - if (!executionStarted && !executionFinished) { - asyncHandler->setTimeoutOccurred(); - if (!dbus_pending_call_get_completed(libdbusPendingCall)) { - dbus_pending_call_cancel(libdbusPendingCall); + asyncHandler->lock(); + bool executionStarted = asyncHandler->getExecutionStarted(); + bool executionFinished = asyncHandler->getExecutionFinished(); + if (!executionStarted && !executionFinished) { + asyncHandler->setTimeoutOccurred(); + if (!dbus_pending_call_get_completed(libdbusPendingCall)) { + dbus_pending_call_cancel(libdbusPendingCall); + } } - } - asyncHandler->unlock(); + asyncHandler->unlock(); - if (executionStarted && !executionFinished) { - // execution of asyncHandler is still running - // ==> add 100 ms for next timeout check - std::get<0>(it->second) = (std::chrono::steady_clock::time_point) std::chrono::steady_clock::now() + std::chrono::milliseconds(100); - } else { - if (!executionFinished) { - // execution of asyncHandler was not finished (and not started) - // => add asyncHandler to mainloopTimeouts list - DBusMessage& dbusMessageCall = std::get<2>(it->second); - - auto lockedContext = mainLoopContext_.lock(); - if (!lockedContext) { - COMMONAPI_ERROR(std::string(__FUNCTION__), "lockedContext == nullptr"); - } else { - { - std::lock_guard<std::mutex> itsLock(mainloopTimeoutsMutex_); - mainloopTimeouts_.push_back(std::make_tuple(asyncHandler, - dbusMessageCall.createMethodError(DBUS_ERROR_TIMEOUT), - CallStatus::REMOTE_ERROR, - nullptr)); + if (executionStarted && !executionFinished) { + // execution of asyncHandler is still running + // ==> add 100 ms for next timeout check + std::get<0>(it->second) = (std::chrono::steady_clock::time_point) std::chrono::steady_clock::now() + std::chrono::milliseconds(100); + } else { + if (!executionFinished) { + // execution of asyncHandler was not finished (and not started) + // => add asyncHandler to mainloopTimeouts list + DBusMessage& dbusMessageCall = std::get<2>(it->second); + + auto lockedContext = mainLoopContext_.lock(); + if (!lockedContext) { + COMMONAPI_ERROR(std::string(__FUNCTION__), "lockedContext == nullptr"); + } else { + { + std::lock_guard<std::mutex> itsLock(mainloopTimeoutsMutex_); + mainloopTimeouts_.push_back(std::make_tuple(asyncHandler, + dbusMessageCall.createMethodError(DBUS_ERROR_TIMEOUT), + CallStatus::REMOTE_ERROR, + nullptr)); + } + lockedContext->wakeup(); } - lockedContext->wakeup(); + it = timeoutMap_.erase(it); + + //This unref MIGHT cause the destruction of the last callback object that references the DBusConnection. + //So after this unref has been called, it has to be ensured that continuation of the loop is an option. + dbus_pending_call_unref(libdbusPendingCall); + } else { + // execution of asyncHandler was finished + it = timeoutMap_.erase(it); + // The deletion of the async handler (which leads to destruction of the DBusProxy and DBusConnection) + // needs to be done asynchronously by the main loop + // because of a potential deadlock. + std::lock_guard<std::mutex> asyncHandlersLock(asyncHandlersToDeleteMutex_); + asyncHandlersToDelete_.push_back(asyncHandler); + proxyPushFunctionToMainLoop(std::bind(&DBusConnection::deleteAsyncHandlers, this)); } + } + } else { + asyncHandler->lock(); + bool executionFinished = asyncHandler->getExecutionFinished(); + asyncHandler->unlock(); + if (executionFinished) { + // execution of asyncHandler was finished but timeout is not expired it = timeoutMap_.erase(it); - - //This unref MIGHT cause the destruction of the last callback object that references the DBusConnection. - //So after this unref has been called, it has to be ensured that continuation of the loop is an option. - dbus_pending_call_unref(libdbusPendingCall); + // The deletion of the async handler (which leads to destruction of the DBusProxy and DBusConnection) + // needs to be done asynchronously by the main loop + // because of a potential deadlock. + std::lock_guard<std::mutex> asyncHandlersLock(asyncHandlersToDeleteMutex_); + asyncHandlersToDelete_.push_back(asyncHandler); + proxyPushFunctionToMainLoop(std::bind(&DBusConnection::deleteAsyncHandlers, this)); } else { - // execution of asyncHandler was finished - it = timeoutMap_.erase(it); - delete asyncHandler; + ++it; } } - } else { + } + } else { + + std::lock_guard<std::mutex> itsLock(enforceTimeoutMutex_); + + auto it = timeoutMap_.begin(); + while (it != timeoutMap_.end()) { + DBusMessageReplyAsyncHandler* asyncHandler = std::get<1>(it->second); asyncHandler->lock(); bool executionFinished = asyncHandler->getExecutionFinished(); asyncHandler->unlock(); if (executionFinished) { // execution of asyncHandler was finished but timeout is not expired it = timeoutMap_.erase(it); - delete asyncHandler; + // The deletion of the async handler (which leads to destruction of the DBusProxy and DBusConnection) + // needs to be done asynchronously by the main loop + // because of a potential deadlock. + std::lock_guard<std::mutex> asyncHandlersLock(asyncHandlersToDeleteMutex_); + asyncHandlersToDelete_.push_back(asyncHandler); + proxyPushFunctionToMainLoop(std::bind(&DBusConnection::deleteAsyncHandlers, this)); } else { ++it; } } } - enforceTimeoutMutex_.unlock(); - } else { - std::lock_guard<std::mutex> itsLock(enforceTimeoutMutex_); - - auto it = timeoutMap_.begin(); - while (it != timeoutMap_.end()) { - DBusMessageReplyAsyncHandler* asyncHandler = std::get<1>(it->second); - asyncHandler->lock(); - bool executionFinished = asyncHandler->getExecutionFinished(); - asyncHandler->unlock(); - if (executionFinished) { - // execution of asyncHandler was finished but timeout is not expired - it = timeoutMap_.erase(it); - delete asyncHandler; - } else { - ++it; - } - } - } - - { - std::lock_guard<std::mutex> itsLock(timeoutInfiniteAsyncHandlersMutex_); - // check for asyncHandler with infinite timeout whose execution is finished - auto it = timeoutInfiniteAsyncHandlers_.begin(); - while (it != timeoutInfiniteAsyncHandlers_.end()) { - DBusMessageReplyAsyncHandler* asyncHandler = (*it); - asyncHandler->lock(); - bool executionFinished = asyncHandler->getExecutionFinished(); - asyncHandler->unlock(); - if ( executionFinished ) { - it = timeoutInfiniteAsyncHandlers_.erase(it); - delete asyncHandler; - } else { - it++; + { + std::lock_guard<std::mutex> itsLock(timeoutInfiniteAsyncHandlersMutex_); + // check for asyncHandler with infinite timeout whose execution is finished + auto it = timeoutInfiniteAsyncHandlers_.begin(); + while (it != timeoutInfiniteAsyncHandlers_.end()) { + DBusMessageReplyAsyncHandler* asyncHandler = (*it); + asyncHandler->lock(); + bool executionFinished = asyncHandler->getExecutionFinished(); + asyncHandler->unlock(); + if ( executionFinished ) { + it = timeoutInfiniteAsyncHandlers_.erase(it); + // The deletion of the async handler (which leads to destruction of the DBusProxy and DBusConnection) + // needs to be done asynchronously by the main loop + // because of a potential deadlock. + std::lock_guard<std::mutex> asyncHandlersLock(asyncHandlersToDeleteMutex_); + asyncHandlersToDelete_.push_back(asyncHandler); + proxyPushFunctionToMainLoop(std::bind(&DBusConnection::deleteAsyncHandlers, this)); + } else { + it++; + } } } } - } + + // delete left async handlers that could not be deleted by the main loop + deleteAsyncHandlers(); } bool DBusConnection::sendDBusMessageWithReplyAsync( @@ -797,35 +819,37 @@ bool DBusConnection::sendDBusMessageWithReplyAsync( std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler, const CommonAPI::CallInfo *_info) const { - std::lock_guard<std::recursive_mutex> dbusConnectionLock(connectionGuard_); - - if (!dbusMessage) { - COMMONAPI_ERROR(std::string(__FUNCTION__), "message == NULL"); - return false; - } - if (!isConnected()) { - COMMONAPI_ERROR(std::string(__FUNCTION__), "not connected"); - return false; - } - DBusPendingCall* libdbusPendingCall; dbus_bool_t libdbusSuccess; + DBusMessageReplyAsyncHandler* replyAsyncHandler = nullptr; + { + std::lock_guard<std::recursive_mutex> dbusConnectionLock(connectionGuard_); - DBusMessageReplyAsyncHandler* replyAsyncHandler = dbusMessageReplyAsyncHandler.release(); + if (!dbusMessage) { + COMMONAPI_ERROR(std::string(__FUNCTION__), "message == NULL"); + return false; + } + if (!isConnected()) { + COMMONAPI_ERROR(std::string(__FUNCTION__), "not connected"); + return false; + } - PendingCallNotificationData* userData = new PendingCallNotificationData(this, replyAsyncHandler); - DBusTimeout::currentTimeout_ = NULL; + replyAsyncHandler = dbusMessageReplyAsyncHandler.release(); - libdbusSuccess = dbus_connection_send_with_reply_set_notify(connection_, - dbusMessage.message_, - &libdbusPendingCall, - onLibdbusPendingCallNotifyThunk, - userData, - onLibdbusDataCleanup, - _info->timeout_); + PendingCallNotificationData* userData = new PendingCallNotificationData(this, replyAsyncHandler); + DBusTimeout::currentTimeout_ = NULL; - if (_info->sender_ != 0) { - COMMONAPI_DEBUG("Message sent: SenderID: ", _info->sender_, " - Serial number: ", dbusMessage.getSerial()); + libdbusSuccess = dbus_connection_send_with_reply_set_notify(connection_, + dbusMessage.message_, + &libdbusPendingCall, + onLibdbusPendingCallNotifyThunk, + userData, + onLibdbusDataCleanup, + _info->timeout_); + + if (_info->sender_ != 0) { + COMMONAPI_DEBUG("Message sent: SenderID: ", _info->sender_, " - Serial number: ", dbusMessage.getSerial()); + } } if (!libdbusSuccess || !libdbusPendingCall) { @@ -864,25 +888,28 @@ bool DBusConnection::sendDBusMessageWithReplyAsync( if(DBusTimeout::currentTimeout_) DBusTimeout::currentTimeout_->setPendingCall(libdbusPendingCall); - enforceTimeoutMutex_.lock(); - auto ret = timeoutMap_.insert( { libdbusPendingCall, toInsert } ); - if (ret.second == false) { - // key has been reused - // update the map value with the new info - DBusMessageReplyAsyncHandler* asyncHandler; - auto it = timeoutMap_.find(ret.first->first); - if(it != timeoutMap_.end()) { - asyncHandler = std::get<1>(it->second); - delete asyncHandler; + DBusMessageReplyAsyncHandler* asyncHandler = nullptr; + { + std::lock_guard<std::mutex> enforcerLock(enforceTimeoutMutex_); + auto ret = timeoutMap_.insert( { libdbusPendingCall, toInsert } ); + if (ret.second == false) { + // key has been reused + // update the map value with the new info + auto it = timeoutMap_.find(ret.first->first); + if(it != timeoutMap_.end()) { + asyncHandler = std::get<1>(it->second); + } + timeoutMap_.erase(ret.first); + timeoutMap_.insert( { libdbusPendingCall, toInsert } ); } - timeoutMap_.erase(ret.first); - timeoutMap_.insert( { libdbusPendingCall, toInsert } ); } - enforceTimeoutMutex_.unlock(); - enforcerThreadMutex_.lock(); + if(asyncHandler) { + delete asyncHandler; + } + + std::lock_guard<std::recursive_mutex> enforcerLock(enforcerThreadMutex_); enforceTimeoutCondition_.notify_one(); - enforcerThreadMutex_.unlock(); } else { // add asyncHandler with infinite timeout to corresponding list std::lock_guard<std::mutex> itsLock(timeoutInfiniteAsyncHandlersMutex_); @@ -928,12 +955,11 @@ void DBusConnection::dispatchDBusMessageReply(const DBusMessage& _reply, bool DBusConnection::singleDispatch() { std::list<MainloopTimeout_t> mainloopTimeouts; { - mainloopTimeoutsMutex_.lock(); + std::lock_guard<std::mutex> itsLock(mainloopTimeoutsMutex_); for (auto t : mainloopTimeouts_) { mainloopTimeouts.push_back(t); } mainloopTimeouts_.clear(); - mainloopTimeoutsMutex_.unlock(); } for (auto t : mainloopTimeouts) { @@ -1116,11 +1142,14 @@ DBusProxyConnection::DBusSignalHandlerToken DBusConnection::addSignalMemberHandl interfaceName, interfaceMemberName, interfaceMemberSignature); - std::lock_guard < std::mutex > dbusSignalLock(signalGuard_); + + std::unique_lock<std::mutex> dbusSignalLock(signalGuard_); auto signalEntry = dbusSignalHandlerTable_.find(dbusSignalHandlerPath); const bool isFirstSignalMemberHandler = (signalEntry == dbusSignalHandlerTable_.end()); + auto itsHandler = dbusSignalHandler.lock(); + if (itsHandler && isFirstSignalMemberHandler) { addLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName, justAddFilter); @@ -1132,9 +1161,31 @@ DBusProxyConnection::DBusSignalHandlerToken DBusConnection::addSignalMemberHandl std::make_pair(std::make_shared<std::recursive_mutex>(), std::move(handlerList)) } ); } else if (itsHandler && !isFirstSignalMemberHandler) { - signalEntry->second.first->lock(); - signalEntry->second.second[itsHandler.get()] = dbusSignalHandler; - signalEntry->second.first->unlock(); + + //get mutex for signal entry + auto signalEntryMutex = signalEntry->second.first; + + // mutex of signal entry must be locked first to avoid potential deadlock + dbusSignalLock.unlock(); + signalEntryMutex->lock(); + + 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); + + std::map<DBusSignalHandler*, std::weak_ptr<DBusSignalHandler>> handlerList; + handlerList[itsHandler.get()] = dbusSignalHandler; + + dbusSignalHandlerTable_.insert( { + dbusSignalHandlerPath, + std::make_pair(std::make_shared<std::recursive_mutex>(), std::move(handlerList)) + } ); + } + signalEntryMutex->unlock(); } return dbusSignalHandlerPath; @@ -1143,18 +1194,27 @@ DBusProxyConnection::DBusSignalHandlerToken DBusConnection::addSignalMemberHandl bool DBusConnection::removeSignalMemberHandler(const DBusSignalHandlerToken &dbusSignalHandlerToken, const DBusSignalHandler* dbusSignalHandler) { bool lastHandlerRemoved = false; - std::lock_guard < std::mutex > dbusSignalLock(signalGuard_); + std::unique_lock<std::mutex> itsLock(signalGuard_); auto signalEntry = dbusSignalHandlerTable_.find(dbusSignalHandlerToken); if (signalEntry != dbusSignalHandlerTable_.end()) { - signalEntry->second.first->lock(); - 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()); + auto signalEntryMutex = signalEntry->second.first; + + // mutex of signal entry must be locked first to avoid potential deadlock + itsLock.unlock(); + signalEntryMutex->lock(); + + 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()); + } } - signalEntry->second.first->unlock(); + signalEntryMutex->unlock(); } if (lastHandlerRemoved) { @@ -1571,42 +1631,72 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() { return isDBusMessageHandled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -template<typename DBusSignalHandlersTable> -void notifyDBusSignalHandlers(DBusSignalHandlersTable& dbusSignalHandlerstable, - typename DBusSignalHandlersTable::iterator& signalEntry, - const CommonAPI::DBus::DBusMessage& dbusMessage, - ::DBusHandlerResult& dbusHandlerResult) { - if (signalEntry == dbusSignalHandlerstable.end() || signalEntry->second.second.empty()) { - dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED; - return; +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); + + if(signalEntry != dbusSignalHandlerTable_.end()) { + signalEntryMutex = signalEntry->second.first; + entryFound = true; + } } - auto handlerEntry = signalEntry->second.second.begin(); - while (handlerEntry != signalEntry->second.second.end()) { - std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler = handlerEntry->second; - if(auto itsHandler = dbusSignalHandler.lock()) - itsHandler->onSignalDBusMessage(dbusMessage); - handlerEntry++; + if(entryFound) { + signalEntryMutex->lock(); + std::lock_guard<std::mutex> itsLock(signalGuard_); + signalEntry = dbusSignalHandlerTable_.find(handlerPath); + } + + // 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()) + itsHandler->onSignalDBusMessage(dbusMessage); + handlerEntry++; + } } dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED; } -template<typename DBusSignalHandlersTable> -void notifyDBusOMSignalHandlers(DBusSignalHandlersTable& dbusSignalHandlerstable, - std::pair<typename DBusSignalHandlersTable::iterator, - typename DBusSignalHandlersTable::iterator>& equalRange, - const CommonAPI::DBus::DBusMessage &dbusMessage, - ::DBusHandlerResult &dbusHandlerResult) { - (void)dbusSignalHandlerstable; +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); - if (equalRange.first != equalRange.second) { - dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED; + if (equalRange.first != equalRange.second) { + dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED; + } + while (equalRange.first != equalRange.second) { + dbusOMSignalHandlers.push_back(equalRange.first->second.second); + equalRange.first++; + } } - while (equalRange.first != equalRange.second) { - std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler = equalRange.first->second.second; - if(auto itsHandler = dbusSignalHandler.lock()) + + for(auto it = dbusOMSignalHandlers.begin(); it != dbusOMSignalHandlers.end(); ++it) { + if(auto itsHandler = it->lock()) itsHandler->onSignalDBusMessage(dbusMessage); - equalRange.first++; } } @@ -1636,40 +1726,23 @@ void notifyDBusOMSignalHandlers(DBusSignalHandlersTable& dbusSignalHandlerstable DBusMessage dbusMessage(libdbusMessage); ::DBusHandlerResult dbusHandlerResult = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - signalGuard_.lock(); - auto signalEntry = dbusSignalHandlerTable_.find(DBusSignalHandlerPath( - objectPath, - interfaceName, - interfaceMemberName, - interfaceMemberSignature)); - - if(signalEntry != dbusSignalHandlerTable_.end()) - signalEntry->second.first->lock(); - signalGuard_.unlock(); + DBusSignalHandlerPath handlerPath = DBusSignalHandlerPath( + objectPath, + interfaceName, + interfaceMemberName, + interfaceMemberSignature); - // ensure, the registry survives - std::shared_ptr<DBusServiceRegistry> itsRegistry_ = DBusServiceRegistry::get(shared_from_this()); - - notifyDBusSignalHandlers(dbusSignalHandlerTable_, - signalEntry, dbusMessage, dbusHandlerResult); - - if(signalEntry != dbusSignalHandlerTable_.end()) - signalEntry->second.first->unlock(); + notifyDBusSignalHandlers(handlerPath, dbusMessage, dbusHandlerResult); if (dbusMessage.hasInterfaceName("org.freedesktop.DBus.ObjectManager")) { + const char* dbusSenderName = dbusMessage.getSender(); if (NULL == dbusSenderName) { COMMONAPI_ERROR(std::string(__FUNCTION__), " dbusSenderName == NULL"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - dbusObjectManagerSignalGuard_.lock(); - auto dbusObjectManagerSignalHandlerIteratorPair = dbusObjectManagerSignalHandlerTable_.equal_range(dbusSenderName); - notifyDBusOMSignalHandlers(dbusObjectManagerSignalHandlerTable_, - dbusObjectManagerSignalHandlerIteratorPair, - dbusMessage, - dbusHandlerResult); - dbusObjectManagerSignalGuard_.unlock(); + notifyDBusOMSignalHandlers(dbusSenderName, dbusMessage, dbusHandlerResult); } return dbusHandlerResult; @@ -1756,5 +1829,20 @@ void DBusConnection::setPendingCallTimedOut(DBusPendingCall* _pendingCall, ::DBu } } +void DBusConnection::deleteAsyncHandlers() { + std::vector<DBusMessageReplyAsyncHandler*> asyncHandlers; + { + std::lock_guard<std::mutex> asyncHandlersLock(asyncHandlersToDeleteMutex_); + asyncHandlers = asyncHandlersToDelete_; + asyncHandlersToDelete_.clear(); + } + + auto it = asyncHandlers.begin(); + while(it != asyncHandlers.end()) { + delete *it; + it = asyncHandlers.erase(it); + } +} + } // namespace DBus } // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusDaemonProxy.cpp b/src/CommonAPI/DBus/DBusDaemonProxy.cpp index 3b5b29f..7c2ce50 100644 --- a/src/CommonAPI/DBus/DBusDaemonProxy.cpp +++ b/src/CommonAPI/DBus/DBusDaemonProxy.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusError.cpp b/src/CommonAPI/DBus/DBusError.cpp index 884f23b..4b51318 100644 --- a/src/CommonAPI/DBus/DBusError.cpp +++ b/src/CommonAPI/DBus/DBusError.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusFactory.cpp b/src/CommonAPI/DBus/DBusFactory.cpp index 31a44c4..99f7e8e 100644 --- a/src/CommonAPI/DBus/DBusFactory.cpp +++ b/src/CommonAPI/DBus/DBusFactory.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -17,19 +17,19 @@ namespace CommonAPI { namespace DBus { -static std::weak_ptr<CommonAPI::Runtime> runtime__; - INITIALIZER(FactoryInit) { - runtime__ = Runtime::get(); - Runtime::get()->registerFactory("dbus", Factory::get()); + Factory::runtime_ = Runtime::get(); + Factory::runtime_.lock()->registerFactory("dbus", Factory::get()); } DEINITIALIZER(FactoryDeinit) { - if (auto rt = runtime__.lock()) { + if (auto rt = Factory::runtime_.lock()) { rt->unregisterFactory("dbus"); } } +std::weak_ptr<CommonAPI::Runtime> Factory::runtime_; + std::shared_ptr<CommonAPI::DBus::Factory> Factory::get() { static std::shared_ptr<Factory> theFactory = std::make_shared<Factory>(); @@ -44,7 +44,7 @@ Factory::~Factory() { void Factory::init() { -#ifndef WIN32 +#ifndef _WIN32 std::lock_guard<std::mutex> itsLock(initializerMutex_); #endif if (!isInitialized_) { @@ -56,7 +56,7 @@ Factory::init() { void Factory::registerInterface(InterfaceInitFunction _function) { -#ifndef WIN32 +#ifndef _WIN32 std::lock_guard<std::mutex> itsLock(initializerMutex_); #endif if (isInitialized_) { diff --git a/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp b/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp index f41b77e..d9c950f 100644 --- a/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp +++ b/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusFunctionalHash.cpp b/src/CommonAPI/DBus/DBusFunctionalHash.cpp index 5e11bfc..c02150a 100644 --- a/src/CommonAPI/DBus/DBusFunctionalHash.cpp +++ b/src/CommonAPI/DBus/DBusFunctionalHash.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusInputStream.cpp b/src/CommonAPI/DBus/DBusInputStream.cpp index 0c838a0..c13353e 100644 --- a/src/CommonAPI/DBus/DBusInputStream.cpp +++ b/src/CommonAPI/DBus/DBusInputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.cpp b/src/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.cpp index a8d538d..8b88753 100644 --- a/src/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.cpp +++ b/src/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusMainLoop.cpp b/src/CommonAPI/DBus/DBusMainLoop.cpp index 5bf27a2..6b3d5e6 100755 --- a/src/CommonAPI/DBus/DBusMainLoop.cpp +++ b/src/CommonAPI/DBus/DBusMainLoop.cpp @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifdef WIN32 +#ifdef _WIN32 #include <WinSock2.h> #include <ws2tcpip.h> #include <atomic> @@ -28,7 +28,7 @@ DBusMainLoop::DBusMainLoop(std::shared_ptr<MainLoopContext> context) currentMinimalTimeoutInterval_(TIMEOUT_INFINITE), hasToStop_(false), isBroken_(false) { -#ifdef WIN32 +#ifdef _WIN32 WSADATA wsaData; int iResult; @@ -188,7 +188,7 @@ DBusMainLoop::~DBusMainLoop() { context_->unsubscribeForTimeouts(timeoutSourceListenerSubscription_); context_->unsubscribeForWakeupEvents(wakeupListenerSubscription_); -#ifdef WIN32 +#ifdef _WIN32 // shutdown the connection since no more data will be sent int iResult = shutdown(wakeFd_.fd, SD_SEND); if (iResult == SOCKET_ERROR) { @@ -403,20 +403,44 @@ bool DBusMainLoop::prepare(const int64_t& timeout) { } void DBusMainLoop::poll() { - int managedFileDescriptorOffset = 0; + + // copy file descriptors + std::vector<DBusMainLoopPollFd> fileDescriptors; { std::lock_guard<std::mutex> itsLock(fileDescriptorsMutex_); - for (auto fileDescriptor = managedFileDescriptors_.begin() + managedFileDescriptorOffset; fileDescriptor != managedFileDescriptors_.end(); ++fileDescriptor) { + for (auto fileDescriptor = managedFileDescriptors_.begin(); + fileDescriptor != managedFileDescriptors_.end(); + ++fileDescriptor) { (*fileDescriptor).revents = 0; + fileDescriptors.push_back(*fileDescriptor); } } -#ifdef WIN32 - int numReadyFileDescriptors = WSAPoll(&managedFileDescriptors_[0], managedFileDescriptors_.size(), int(currentMinimalTimeoutInterval_)); +#ifdef _WIN32 + int numReadyFileDescriptors = WSAPoll(&fileDescriptors[0], fileDescriptors.size(), int(currentMinimalTimeoutInterval_)); #else - int numReadyFileDescriptors = ::poll(&(managedFileDescriptors_[0]), - managedFileDescriptors_.size(), int(currentMinimalTimeoutInterval_)); + int numReadyFileDescriptors = ::poll(&(fileDescriptors[0]), + fileDescriptors.size(), int(currentMinimalTimeoutInterval_)); #endif + + // update file descriptors + { + std::lock_guard<std::mutex> itsLock(fileDescriptorsMutex_); + for (auto itFds = fileDescriptors.begin(); + itFds != fileDescriptors.end(); + itFds++) { + for(auto itManagedFds = managedFileDescriptors_.begin(); + itManagedFds != managedFileDescriptors_.end(); + ++itManagedFds) { + if((*itFds).fd == (*itManagedFds).fd && + (*itFds).events == (*itManagedFds).events) { + (*itManagedFds).revents = (*itFds).revents; + continue; + } + } + } + } + if (!numReadyFileDescriptors) { int64_t currentContextTime = getCurrentTimeInMs(); @@ -449,6 +473,7 @@ void DBusMainLoop::poll() { } // If the wakeup descriptor woke us up, we must acknowledge + std::lock_guard<std::mutex> itsLock(fileDescriptorsMutex_); if (managedFileDescriptors_[0].revents) { wakeupAck(); } @@ -564,7 +589,7 @@ void DBusMainLoop::dispatch() { } void DBusMainLoop::wakeup() { -#ifdef WIN32 +#ifdef _WIN32 // Send an initial buffer char *sendbuf = "1"; @@ -585,7 +610,7 @@ void DBusMainLoop::wakeup() { } void DBusMainLoop::wakeupAck() { -#ifdef WIN32 +#ifdef _WIN32 // Receive until the peer closes the connection int iResult; char recvbuf[DEFAULT_BUFLEN]; @@ -704,7 +729,7 @@ void DBusMainLoop::registerWatch(Watch* watch, std::lock_guard<std::mutex> itsLock(watchesMutex_); std::mutex* mtx = new std::mutex; -#ifdef WIN32 +#ifdef _WIN32 std::atomic_signal_fence(std::memory_order_acq_rel); #else asm volatile ("":::"memory"); diff --git a/src/CommonAPI/DBus/DBusMainLoopContext.cpp b/src/CommonAPI/DBus/DBusMainLoopContext.cpp index 3124027..c44c16d 100644 --- a/src/CommonAPI/DBus/DBusMainLoopContext.cpp +++ b/src/CommonAPI/DBus/DBusMainLoopContext.cpp @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifdef WIN32 +#ifdef _WIN32 #include <WinSock2.h> #include <ws2tcpip.h> #else @@ -48,25 +48,20 @@ DBusQueueDispatchSource::DBusQueueDispatchSource(DBusQueueWatch* watch) : } DBusQueueDispatchSource::~DBusQueueDispatchSource() { - std::unique_lock<std::mutex> itsLock(watchMutex_); watch_->removeDependentDispatchSource(this); } bool DBusQueueDispatchSource::prepare(int64_t& timeout) { - std::unique_lock<std::mutex> itsLock(watchMutex_); timeout = -1; return !watch_->emptyQueue(); } bool DBusQueueDispatchSource::check() { - std::unique_lock<std::mutex> itsLock(watchMutex_); return !watch_->emptyQueue(); } bool DBusQueueDispatchSource::dispatch() { - std::unique_lock<std::mutex> itsLock(watchMutex_); - if (!watch_->emptyQueue()) { - auto queueEntry = watch_->frontQueue(); + if (auto queueEntry = watch_->frontQueue()) { watch_->popQueue(); watch_->processQueueEntry(queueEntry); } @@ -101,7 +96,7 @@ void DBusWatch::startWatching() { pollFlags |= POLLOUT; } -#ifdef WIN32 +#ifdef _WIN32 pollFileDescriptor_.fd = dbus_watch_get_socket(libdbusWatch_); wsaEvent_ = WSACreateEvent(); WSAEventSelect(pollFileDescriptor_.fd, wsaEvent_, FD_READ); @@ -131,14 +126,14 @@ const pollfd& DBusWatch::getAssociatedFileDescriptor() { return pollFileDescriptor_; } -#ifdef WIN32 +#ifdef _WIN32 const HANDLE& DBusWatch::getAssociatedEvent() { return wsaEvent_; } #endif void DBusWatch::dispatch(unsigned int eventFlags) { -#ifdef WIN32 +#ifdef _WIN32 unsigned int dbusWatchFlags = 0; if (eventFlags & (POLLRDBAND | POLLRDNORM)) { @@ -173,15 +168,17 @@ void DBusWatch::dispatch(unsigned int eventFlags) { } const std::vector<DispatchSource*>& DBusWatch::getDependentDispatchSources() { + std::lock_guard<std::mutex> itsLock(dependentDispatchSourcesMutex_); return dependentDispatchSources_; } void DBusWatch::addDependentDispatchSource(DispatchSource* dispatchSource) { + std::lock_guard<std::mutex> itsLock(dependentDispatchSourcesMutex_); dependentDispatchSources_.push_back(dispatchSource); } DBusQueueWatch::DBusQueueWatch(std::shared_ptr<DBusConnection> _connection) : pipeValue_(4) { -#ifdef WIN32 +#ifdef _WIN32 WSADATA wsaData; int iResult; @@ -316,7 +313,7 @@ DBusQueueWatch::DBusQueueWatch(std::shared_ptr<DBusConnection> _connection) : pi } DBusQueueWatch::~DBusQueueWatch() { -#ifdef WIN32 +#ifdef _WIN32 // shutdown the connection since no more data will be sent int iResult = shutdown(pipeFileDescriptors_[0], SD_SEND); if (iResult == SOCKET_ERROR) { @@ -348,21 +345,24 @@ const pollfd& DBusQueueWatch::getAssociatedFileDescriptor() { return pollFileDescriptor_; } -#ifdef WIN32 +#ifdef _WIN32 const HANDLE& DBusQueueWatch::getAssociatedEvent() { return wsaEvent_; } #endif const std::vector<DispatchSource*>& DBusQueueWatch::getDependentDispatchSources() { + std::lock_guard<std::mutex> itsLock(dependentDispatchSourcesMutex_); return dependentDispatchSources_; } void DBusQueueWatch::addDependentDispatchSource(CommonAPI::DispatchSource* _dispatchSource) { + std::lock_guard<std::mutex> itsLock(dependentDispatchSourcesMutex_); dependentDispatchSources_.push_back(_dispatchSource); } void DBusQueueWatch::removeDependentDispatchSource(CommonAPI::DispatchSource* _dispatchSource) { + std::lock_guard<std::mutex> itsLock(dependentDispatchSourcesMutex_); std::vector<CommonAPI::DispatchSource*>::iterator it; for (it = dependentDispatchSources_.begin(); it != dependentDispatchSources_.end(); it++) { @@ -377,7 +377,7 @@ void DBusQueueWatch::pushQueue(std::shared_ptr<QueueEntry> _queueEntry) { std::unique_lock<std::mutex> itsLock(queueMutex_); queue_.push(_queueEntry); -#ifdef WIN32 +#ifdef _WIN32 // Send an initial buffer char *sendbuf = "1"; @@ -399,7 +399,7 @@ void DBusQueueWatch::pushQueue(std::shared_ptr<QueueEntry> _queueEntry) { void DBusQueueWatch::popQueue() { std::unique_lock<std::mutex> itsLock(queueMutex_); -#ifdef WIN32 +#ifdef _WIN32 // Receive until the peer closes the connection int iResult; char recvbuf[1]; @@ -428,7 +428,11 @@ void DBusQueueWatch::popQueue() { std::shared_ptr<QueueEntry> DBusQueueWatch::frontQueue() { std::unique_lock<std::mutex> itsLock(queueMutex_); - return queue_.front(); + if(queue_.empty()) { + return NULL; + } else { + return queue_.front(); + } } bool DBusQueueWatch::emptyQueue() { @@ -444,7 +448,7 @@ void DBusQueueWatch::processQueueEntry(std::shared_ptr<QueueEntry> _queueEntry) } } -#ifdef WIN32 +#ifdef _WIN32 __declspec(thread) DBusTimeout* DBusTimeout::currentTimeout_ = NULL; #else thread_local DBusTimeout* DBusTimeout::currentTimeout_ = NULL; diff --git a/src/CommonAPI/DBus/DBusMessage.cpp b/src/CommonAPI/DBus/DBusMessage.cpp index 927624c..9321315 100644 --- a/src/CommonAPI/DBus/DBusMessage.cpp +++ b/src/CommonAPI/DBus/DBusMessage.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusObjectManager.cpp b/src/CommonAPI/DBus/DBusObjectManager.cpp index c9484fd..85fdbf4 100644 --- a/src/CommonAPI/DBus/DBusObjectManager.cpp +++ b/src/CommonAPI/DBus/DBusObjectManager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusObjectManagerStub.cpp b/src/CommonAPI/DBus/DBusObjectManagerStub.cpp index 20bbf1d..226c825 100644 --- a/src/CommonAPI/DBus/DBusObjectManagerStub.cpp +++ b/src/CommonAPI/DBus/DBusObjectManagerStub.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusOutputStream.cpp b/src/CommonAPI/DBus/DBusOutputStream.cpp index 564aa61..ae42e36 100644 --- a/src/CommonAPI/DBus/DBusOutputStream.cpp +++ b/src/CommonAPI/DBus/DBusOutputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusProxy.cpp b/src/CommonAPI/DBus/DBusProxy.cpp index 2d19670..ef6388b 100644 --- a/src/CommonAPI/DBus/DBusProxy.cpp +++ b/src/CommonAPI/DBus/DBusProxy.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -93,7 +93,6 @@ void DBusProxy::availabilityTimeoutThreadHandler() const { if (now > std::get<0>(*it)) { //timeout - availabilityMutex_.lock(); std::chrono::steady_clock::time_point timepoint_; if(isAvailable()) callbacks.push_back(std::make_tuple(callback, std::move(std::get<2>(*it)), @@ -104,10 +103,8 @@ void DBusProxy::availabilityTimeoutThreadHandler() const { AvailabilityStatus::NOT_AVAILABLE, timepoint_)); it = timeouts_.erase(it); - availabilityMutex_.unlock(); } else { //timeout not expired - availabilityMutex_.lock(); if(isAvailable()) { callbacks.push_back(std::make_tuple(callback, std::move(std::get<2>(*it)), AvailabilityStatus::AVAILABLE, @@ -116,7 +113,6 @@ void DBusProxy::availabilityTimeoutThreadHandler() const { } else { ++it; } - availabilityMutex_.unlock(); } } @@ -134,7 +130,6 @@ void DBusProxy::availabilityTimeoutThreadHandler() const { while (it != timeouts_.end()) { isAvailableAsyncCallback callback = std::get<1>(*it); - availabilityMutex_.lock(); if(isAvailable()) { callbacks.push_back(std::make_tuple(callback, std::move(std::get<2>(*it)), AvailabilityStatus::AVAILABLE, @@ -143,7 +138,6 @@ void DBusProxy::availabilityTimeoutThreadHandler() const { } else { ++it; } - availabilityMutex_.unlock(); } timeoutsMutex_.unlock(); @@ -214,6 +208,7 @@ DBusProxy::~DBusProxy() { } bool DBusProxy::isAvailable() const { + std::lock_guard<std::mutex>itsLock(availabilityMutex_); return (availabilityStatus_ == AvailabilityStatus::AVAILABLE); } @@ -221,7 +216,7 @@ bool DBusProxy::isAvailableBlocking() const { std::unique_lock<std::mutex> lock(availabilityMutex_); if(!getDBusConnection()->hasDispatchThread()) { - return isAvailable(); + return (availabilityStatus_ == AvailabilityStatus::AVAILABLE); } while (availabilityStatus_ != AvailabilityStatus::AVAILABLE) { diff --git a/src/CommonAPI/DBus/DBusProxyBase.cpp b/src/CommonAPI/DBus/DBusProxyBase.cpp index 3052f9e..d24e58b 100644 --- a/src/CommonAPI/DBus/DBusProxyBase.cpp +++ b/src/CommonAPI/DBus/DBusProxyBase.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusProxyManager.cpp b/src/CommonAPI/DBus/DBusProxyManager.cpp index cedd58b..a522bf4 100644 --- a/src/CommonAPI/DBus/DBusProxyManager.cpp +++ b/src/CommonAPI/DBus/DBusProxyManager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/CommonAPI/DBus/DBusServiceRegistry.cpp b/src/CommonAPI/DBus/DBusServiceRegistry.cpp index 7ad5987..4ef9fbc 100644 --- a/src/CommonAPI/DBus/DBusServiceRegistry.cpp +++ b/src/CommonAPI/DBus/DBusServiceRegistry.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -22,7 +22,7 @@ static CommonAPI::CallInfo serviceRegistryInfo(10000); std::shared_ptr<DBusServiceRegistry> DBusServiceRegistry::get(std::shared_ptr<DBusProxyConnection> _connection) { - std::lock_guard<std::mutex> itsGuard(registriesMutex_); + std::unique_lock<std::mutex> itsGuard(registriesMutex_); auto registries = getRegistryMap(); auto registryIterator = registries->find(_connection); if (registryIterator != registries->end()) @@ -31,8 +31,9 @@ DBusServiceRegistry::get(std::shared_ptr<DBusProxyConnection> _connection) { std::shared_ptr<DBusServiceRegistry> registry = std::make_shared<DBusServiceRegistry>(_connection); if (registry) { - registry->init(); registries->insert( { _connection, registry } ); + itsGuard.unlock(); + registry->init(); } return registry; } @@ -108,13 +109,13 @@ DBusServiceRegistry::subscribeAvailabilityListener( DBusAddress dbusAddress; translator_->translate(_address, dbusAddress); + dbusServicesMutex_.lock(); if (notificationThread_ == std::this_thread::get_id()) { COMMONAPI_ERROR( "You must not build proxies in callbacks of ProxyStatusEvent.", " Please refer to the documentation for suggestions how to avoid this."); } - dbusServicesMutex_.lock(); auto& dbusServiceListenersRecord = dbusServiceListenersMap[dbusAddress.getService()]; if (dbusServiceListenersRecord.uniqueBusNameState == DBusRecordState::AVAILABLE) { COMMONAPI_ERROR(std::string(__FUNCTION__), " uniqueBusName ", dbusServiceListenersRecord.uniqueBusName, " already AVAILABLE"); @@ -610,15 +611,6 @@ DBusServiceRegistry::getDBusObjectPathCacheReference( DBusUniqueNameRecord& dbusUniqueNameRecord) { const bool isFirstDBusObjectPathCache = dbusUniqueNameRecord.dbusObjectPathsCache.empty(); - auto dbusObjectPathCacheIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); - if(dbusObjectPathCacheIterator == dbusUniqueNameRecord.dbusObjectPathsCache.end()) { - DBusObjectPathCache objectPathCache; - objectPathCache.serviceName = dbusServiceName; - std::unordered_map<std::string, DBusObjectPathCache>::value_type value (dbusObjectPath, std::move(objectPathCache)); - dbusUniqueNameRecord.dbusObjectPathsCache.insert(std::move(value)); - dbusObjectPathCacheIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); - } - if (isFirstDBusObjectPathCache) { auto dbusProxyConnection = dbusDaemonProxy_->getDBusConnection(); const bool isSubscriptionSuccessful = dbusProxyConnection->addObjectManagerSignalMemberHandler( @@ -629,6 +621,15 @@ DBusServiceRegistry::getDBusObjectPathCacheReference( } } + auto dbusObjectPathCacheIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); + if(dbusObjectPathCacheIterator == dbusUniqueNameRecord.dbusObjectPathsCache.end()) { + DBusObjectPathCache objectPathCache; + objectPathCache.serviceName = dbusServiceName; + std::unordered_map<std::string, DBusObjectPathCache>::value_type value (dbusObjectPath, std::move(objectPathCache)); + dbusUniqueNameRecord.dbusObjectPathsCache.insert(std::move(value)); + dbusObjectPathCacheIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); + } + if (dbusObjectPathCacheIterator->second.state == DBusRecordState::UNKNOWN && resolveObjectPathWithObjectManager(dbusServiceUniqueName, dbusObjectPath)) { dbusObjectPathCacheIterator->second.state = DBusRecordState::RESOLVING; @@ -677,7 +678,6 @@ void DBusServiceRegistry::releaseDBusObjectPathCacheReference(const std::string& const bool isLastDBusObjectPathCache = dbusUniqueNameRecord.dbusObjectPathsCache.empty(); if (isLastDBusObjectPathCache) { - dbusServicesMutex_.unlock(); auto dbusProxyConnection = dbusDaemonProxy_->getDBusConnection(); const bool isSubscriptionCancelled = dbusProxyConnection->removeObjectManagerSignalMemberHandler( dbusServiceListenersRecord.uniqueBusName, @@ -685,7 +685,6 @@ void DBusServiceRegistry::releaseDBusObjectPathCacheReference(const std::string& if (!isSubscriptionCancelled) { COMMONAPI_ERROR(std::string(__FUNCTION__), ": still subscribed too ", dbusServiceListenersRecord.uniqueBusName); } - dbusServicesMutex_.lock(); } } } @@ -778,9 +777,9 @@ void DBusServiceRegistry::onGetManagedObjectsCallbackResolve(const CallStatus& c const std::string& dbusServiceUniqueName, const std::string& dbusObjectPath) { + dbusServicesMutex_.lock(); if(callStatus == CallStatus::SUCCESS) { //has object manager - bool objectPathFound = false; for(auto objectPathDict : availableServiceInstances) { std::string objectPath = objectPathDict.first; @@ -788,38 +787,36 @@ void DBusServiceRegistry::onGetManagedObjectsCallbackResolve(const CallStatus& c continue; // object path that should be resolved is found --> resolve - objectPathFound = true; CommonAPI::DBus::DBusObjectManagerStub::DBusInterfacesAndPropertiesDict interfacesAndPropertiesDict = objectPathDict.second; for(auto interfaceDict : interfacesAndPropertiesDict) { std::string interfaceName = interfaceDict.first; - dbusServicesMutex_.lock(); processManagedObject(dbusObjectPath, dbusServiceUniqueName, interfaceName); - dbusServicesMutex_.unlock(); } } - if(!objectPathFound) { + // resolve further interfaces with the help of the manager + bool managerFound = false; + std::string objectPathManager = dbusObjectPath.substr(0, dbusObjectPath.find_last_of("\\/")); + for(auto objectPathDict : availableServiceInstances) + { + // check if the main part of the object path is in the list. // if it is, the object path could be managed. // else, it maybe existed a while back but is now gone, in which case just ignore. + std::string objectPath = objectPathDict.first; + if (dbusObjectPath.substr(0, objectPath.size()) != objectPath) + continue; - std::string objectPathManager = dbusObjectPath.substr(0, dbusObjectPath.find_last_of("\\/")); - for(auto objectPathDict : availableServiceInstances) - { - - std::string objectPath = objectPathDict.first; - - if (dbusObjectPath.substr(0, objectPath.size()) != objectPath) - continue; - - // also check that the next character in dbusObject path is a slash or a backslash, - // so that we can make sure that we have compared against a full path element + // also check that the next character in dbusObject path is a slash or a backslash, + // so that we can make sure that we have compared against a full path element + if(dbusObjectPath != objectPath) { auto delimiter = dbusObjectPath.at(objectPath.size()); if (delimiter != '\\' && delimiter != '/') continue; - // object path is managed. Try to resolve object path with the help of the manager + managerFound = true; + auto getManagedObjectsCallback = std::bind( &DBusServiceRegistry::onGetManagedObjectsCallbackResolve, shared_from_this(), @@ -828,13 +825,41 @@ void DBusServiceRegistry::onGetManagedObjectsCallbackResolve(const CallStatus& c dbusServiceUniqueName, dbusObjectPath); getManagedObjectsAsync(dbusServiceUniqueName, objectPathManager, getManagedObjectsCallback); + } + } + + if(!managerFound) { + //mark object path as resolved + auto dbusServiceUniqueNameIterator = dbusUniqueNamesMap_.find(dbusServiceUniqueName); + const bool isDBusServiceUniqueNameFound = (dbusServiceUniqueNameIterator != dbusUniqueNamesMap_.end()); + + if (!isDBusServiceUniqueNameFound) { + dbusServicesMutex_.unlock(); + return; + } + + DBusUniqueNameRecord& dbusUniqueNameRecord = dbusServiceUniqueNameIterator->second; + auto dbusObjectPathIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); + const bool isDBusObjectPathFound = (dbusObjectPathIterator != dbusUniqueNameRecord.dbusObjectPathsCache.end()); + + if (!isDBusObjectPathFound) { + dbusServicesMutex_.unlock(); + return; } + DBusObjectPathCache& dbusObjectPathRecord = dbusObjectPathIterator->second; + + dbusObjectPathRecord.state = DBusRecordState::RESOLVED; + if(dbusObjectPathRecord.futureOnResolve.valid()) + dbusObjectPathRecord.promiseOnResolve.set_value(dbusObjectPathRecord.state); + + dbusUniqueNameRecord.objectPathsState = DBusRecordState::RESOLVED; } } else { COMMONAPI_ERROR("There is no Object Manager that manages " + dbusObjectPath + ". Resolving failed!"); } + dbusServicesMutex_.unlock(); } void DBusServiceRegistry::processManagedObject(const std::string& dbusObjectPath, @@ -862,12 +887,6 @@ void DBusServiceRegistry::processManagedObject(const std::string& dbusObjectPath dbusObjectPathRecord.dbusInterfaceNamesCache.insert(interfaceName); } - dbusObjectPathRecord.state = DBusRecordState::RESOLVED; - if(dbusObjectPathRecord.futureOnResolve.valid()) - dbusObjectPathRecord.promiseOnResolve.set_value(dbusObjectPathRecord.state); - - dbusUniqueNameRecord.objectPathsState = DBusRecordState::RESOLVED; - notifyDBusServiceListeners( dbusUniqueNameRecord, dbusObjectPath, @@ -981,7 +1000,19 @@ void DBusServiceRegistry::onDBusServiceNotAvailable(DBusServiceListenersRecord& for (auto dbusObjectPathListenersIterator = dbusServiceListenersRecord.dbusObjectPathListenersMap.begin(); dbusObjectPathListenersIterator != dbusServiceListenersRecord.dbusObjectPathListenersMap.end(); ) { auto& dbusInterfaceNameListenersMap = dbusObjectPathListenersIterator->second; - notifyDBusObjectPathResolved(dbusInterfaceNameListenersMap, dbusInterfaceNamesCache); + + for (auto dbusInterfaceNameListenersIterator = dbusInterfaceNameListenersMap.begin(); + dbusInterfaceNameListenersIterator != dbusInterfaceNameListenersMap.end();) { + auto& dbusInterfaceNameListenersRecord = dbusInterfaceNameListenersIterator->second; + + notifyDBusInterfaceNameListeners(dbusInterfaceNameListenersRecord, false); + + if (dbusInterfaceNameListenersRecord.listenerList.empty()) { + dbusInterfaceNameListenersIterator = dbusInterfaceNameListenersMap.erase(dbusInterfaceNameListenersIterator); + } else { + dbusInterfaceNameListenersIterator++; + } + } if (dbusInterfaceNameListenersMap.empty()) { dbusObjectPathListenersIterator = dbusServiceListenersRecord.dbusObjectPathListenersMap.erase( @@ -1036,19 +1067,21 @@ void DBusServiceRegistry::notifyDBusServiceListeners(const DBusUniqueNameRecord& void DBusServiceRegistry::notifyDBusObjectPathResolved(DBusInterfaceNameListenersMap& dbusInterfaceNameListenersMap, const std::unordered_set<std::string>& dbusInterfaceNames) { - for (auto dbusObjectPathListenersIterator = dbusInterfaceNameListenersMap.begin(); - dbusObjectPathListenersIterator != dbusInterfaceNameListenersMap.end();) { - const auto& listenersDBusInterfaceName = dbusObjectPathListenersIterator->first; - auto& dbusInterfaceNameListenersRecord = dbusObjectPathListenersIterator->second; + for (auto dbusInterfaceNameListenersIterator = dbusInterfaceNameListenersMap.begin(); + dbusInterfaceNameListenersIterator != dbusInterfaceNameListenersMap.end();) { + const auto& listenersDBusInterfaceName = dbusInterfaceNameListenersIterator->first; + auto& dbusInterfaceNameListenersRecord = dbusInterfaceNameListenersIterator->second; const auto& dbusInterfaceNameIterator = dbusInterfaceNames.find(listenersDBusInterfaceName); - const bool isDBusInterfaceNameAvailable = (dbusInterfaceNameIterator != dbusInterfaceNames.end()); - notifyDBusInterfaceNameListeners(dbusInterfaceNameListenersRecord, isDBusInterfaceNameAvailable); + + if(dbusInterfaceNameIterator != dbusInterfaceNames.end()) { + notifyDBusInterfaceNameListeners(dbusInterfaceNameListenersRecord, true); + } if (dbusInterfaceNameListenersRecord.listenerList.empty()) { - dbusObjectPathListenersIterator = dbusInterfaceNameListenersMap.erase(dbusObjectPathListenersIterator); + dbusInterfaceNameListenersIterator = dbusInterfaceNameListenersMap.erase(dbusInterfaceNameListenersIterator); } else { - dbusObjectPathListenersIterator++; + dbusInterfaceNameListenersIterator++; } } } @@ -1100,8 +1133,9 @@ void DBusServiceRegistry::notifyDBusInterfaceNameListeners(DBusInterfaceNameList dbusInterfaceNameListenersRecord.listenersToRemove.remove(dbusServiceListenerIterator->first); dbusServiceListenerIterator = dbusInterfaceNameListenersRecord.listenerList.erase(dbusServiceListenerIterator); } else { - if(auto itsProxy = dbusServiceListenerIterator->second->proxy.lock()) + if(auto itsProxy = dbusServiceListenerIterator->second->proxy.lock()) { (dbusServiceListenerIterator->second->listener)(itsProxy, availabilityStatus); + } ++dbusServiceListenerIterator; } } @@ -1119,14 +1153,12 @@ void DBusServiceRegistry::removeUniqueName(const DBusUniqueNamesMapIterator& dbu if (dbusUniqueNamesIterator->second.ownedBusNames.size() == 0) { std::string dbusUniqueName = dbusUniqueNamesIterator->first; dbusUniqueNamesMap_.erase(dbusUniqueNamesIterator); - dbusServicesMutex_.unlock(); const bool isSubscriptionCancelled = dbusDaemonProxy_->getDBusConnection()->removeObjectManagerSignalMemberHandler( dbusUniqueName, this); if (!isSubscriptionCancelled) { COMMONAPI_ERROR(std::string(__FUNCTION__), ": still subscribed too ", dbusUniqueName); } - dbusServicesMutex_.lock(); } else { //delete object path cache entry of service auto& dbusObjectPathsCache = dbusUniqueNamesIterator->second.dbusObjectPathsCache; diff --git a/src/CommonAPI/DBus/DBusStubAdapter.cpp b/src/CommonAPI/DBus/DBusStubAdapter.cpp index 0f86cc1..44ed866 100644 --- a/src/CommonAPI/DBus/DBusStubAdapter.cpp +++ b/src/CommonAPI/DBus/DBusStubAdapter.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index be5aa1e..5ae19c9 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/test/DBusClientIdTest.cpp b/src/test/DBusClientIdTest.cpp index 1a75943..d94a4aa 100644 --- a/src/test/DBusClientIdTest.cpp +++ b/src/test/DBusClientIdTest.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/test/DBusConnectionTest.cpp b/src/test/DBusConnectionTest.cpp index 1e999f3..5f66707 100644 --- a/src/test/DBusConnectionTest.cpp +++ b/src/test/DBusConnectionTest.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/test/DBusDaemonProxyTest.cpp b/src/test/DBusDaemonProxyTest.cpp index b2a4364..4bb9d80 100644 --- a/src/test/DBusDaemonProxyTest.cpp +++ b/src/test/DBusDaemonProxyTest.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/test/DBusStubAdapterTest.cpp b/src/test/DBusStubAdapterTest.cpp index 5c1d742..387aec9 100644 --- a/src/test/DBusStubAdapterTest.cpp +++ b/src/test/DBusStubAdapterTest.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/test/DBusVariantOutputStreamTest.cpp b/src/test/DBusVariantOutputStreamTest.cpp index b23e12f..b68f3ac 100644 --- a/src/test/DBusVariantOutputStreamTest.cpp +++ b/src/test/DBusVariantOutputStreamTest.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/src/test/DBusVariantTest.cpp b/src/test/DBusVariantTest.cpp index b2b4b8b..88800cb 100644 --- a/src/test/DBusVariantTest.cpp +++ b/src/test/DBusVariantTest.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// Copyright (C) 2013-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. |