diff --git a/CHANGES b/CHANGES index 3dde05f..173075d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,9 @@ Changes ======= +v3.1.12.2 +- Fixed hang-up in proxy destruction when async method call was done and proxy is not available +- DBus connections are now released even if they were not created with the Factory interface + v3.1.12.1 - Fixed race condition for managed services. When a managed services was removed, an appropriate availability status changed event was received (service became unavailable) and afterwards a 'getAvailablStatusAsync' call for the removed service instance was done, the response could be that diff --git a/CMakeLists.txt b/CMakeLists.txt index f0e1c59..e98d655 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -169,7 +169,7 @@ endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCOMMONAPI_LOGLEVEL=COMMONAPI_LOGLEVEL_${MAX_LOG_LEVEL}") -message(STATUS "Compiler options: ${CMAKE_CXX_FLAGS}") +message(STATUS "Compiler options: ${CMAKE_CXX_FLAGS}") include_directories( include @@ -325,7 +325,7 @@ else() COMMAND asciidoc -a version=${PACKAGE_VERSION} -b html - -o doc/html/README.html + -o doc/html/README.html ${PROJECT_BINARY_DIR}/../README) endif() endif() @@ -360,6 +360,10 @@ if ("${BUILD_SHARED_LIBS}" STREQUAL "ON") set(BUILD_SHARED_LIBS OFF) set(BUILD_SHARED_LIBS_AUTOMATIC_OFF 1) endif() +# ...but visual studio needs a shared CRT for gtest, otherwise the linker won't work correctly with the testcases. +if (MSVC) + set( gtest_force_shared_crt ON CACHE BOOL "Always use msvcrt.dll" ) +endif() add_subdirectory(${GTEST_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/gtest EXCLUDE_FROM_ALL) if ("${BUILD_SHARED_LIBS_AUTOMATIC_OFF}" STREQUAL "1") set(BUILD_SHARED_LIBS ON) @@ -382,4 +386,3 @@ add_dependencies(check build_tests) # add test directory add_subdirectory( src/test EXCLUDE_FROM_ALL ) - diff --git a/include/CommonAPI/DBus/DBusProxy.hpp b/include/CommonAPI/DBus/DBusProxy.hpp index 403ce21..9a85a8d 100644 --- a/include/CommonAPI/DBus/DBusProxy.hpp +++ b/include/CommonAPI/DBus/DBusProxy.hpp @@ -173,6 +173,7 @@ class COMMONAPI_EXPORT_CLASS_EXPLICIT DBusProxy mutable std::list timeouts_; std::atomic everAvailable_; + mutable std::atomic cancelAvailabilityTimeoutThread_; }; diff --git a/src/CommonAPI/DBus/DBusConnection.cpp b/src/CommonAPI/DBus/DBusConnection.cpp index d9da52e..4206f95 100644 --- a/src/CommonAPI/DBus/DBusConnection.cpp +++ b/src/CommonAPI/DBus/DBusConnection.cpp @@ -67,13 +67,20 @@ class CompletionHelper { } bool forceDetach(false); - if (0u != activeConnections) { - std::future ready = readyToCleanup_.get_future(); - if (ready.valid()) { - const std::future_status status = ready.wait_for(std::chrono::seconds(1)); - forceDetach = (std::future_status::ready != status); + #if defined (_MSC_VER) && (_MSC_VER < 1900) + // MSVC compiler RTL is buggy until fixed in Visual Studio 2015 + // The code crashes when doing a wait_for() in a static destructor + // So, skip the check if we have an older version of MSVC + forceDetach = true; + #else + if (0u != activeConnections) { + std::future ready = readyToCleanup_.get_future(); + if (ready.valid()) { + const std::future_status status = ready.wait_for(std::chrono::seconds(1)); + forceDetach = (std::future_status::ready != status); + } } - } + #endif { std::lock_guard lock(mutex_); @@ -465,6 +472,7 @@ void DBusConnection::disconnect() { isDisconnecting_ = true; if (std::shared_ptr mainLoopContext = mainLoopContext_.lock()) { + DBusServiceRegistry::remove(shared_from_this()); Factory::get()->releaseConnection(connectionId_); } @@ -1264,7 +1272,7 @@ bool DBusConnection::removeSignalMemberHandler(const DBusSignalHandlerToken &dbu bool lastHandlerRemoved = false; std::lock_guard dbusSignalHandlersLock(signalHandlersGuard_); - + auto signalHandlerPathIt = dbusSignalHandlers_.find(dbusSignalHandlerToken); if (signalHandlerPathIt != dbusSignalHandlers_.end()) { diff --git a/src/CommonAPI/DBus/DBusFactory.cpp b/src/CommonAPI/DBus/DBusFactory.cpp index 2490e98..2006f5a 100644 --- a/src/CommonAPI/DBus/DBusFactory.cpp +++ b/src/CommonAPI/DBus/DBusFactory.cpp @@ -88,7 +88,7 @@ Factory::createProxy( if (proxyCreateFunctionsIterator != proxyCreateFunctions_.end()) { CommonAPI::Address address(_domain, _interface, _instance); DBusAddress dbusAddress; - + if (DBusAddressTranslator::get()->translate(address, dbusAddress)) { std::shared_ptr connection = getConnection(_connectionId); @@ -113,7 +113,7 @@ Factory::createProxy( if (proxyCreateFunctionsIterator != proxyCreateFunctions_.end()) { CommonAPI::Address address(_domain, _interface, _instance); DBusAddress dbusAddress; - + if (DBusAddressTranslator::get()->translate(address, dbusAddress)) { std::shared_ptr connection = getConnection(_context); @@ -188,7 +188,7 @@ Factory::unregisterStub(const std::string &_domain, const std::string &_interfac const auto _adapter = adapterResult->second; const auto &connection = _adapter->getDBusConnection(); const auto objectManager = connection->getDBusObjectManager(); - + if (!objectManager->unregisterDBusStubAdapter(_adapter)) { return false; } @@ -462,7 +462,6 @@ void Factory::releaseConnection(const ConnectionId_t& _connectionId) { auto itsConnection = connections_.find(_connectionId); if (itsConnection != connections_.end()) { - DBusServiceRegistry::remove(itsConnection->second); connections_.erase(_connectionId); } } diff --git a/src/CommonAPI/DBus/DBusProxy.cpp b/src/CommonAPI/DBus/DBusProxy.cpp index eef22b4..0b5b14c 100644 --- a/src/CommonAPI/DBus/DBusProxy.cpp +++ b/src/CommonAPI/DBus/DBusProxy.cpp @@ -50,7 +50,7 @@ void DBusProxyStatusEvent::onListenerRemoved(const Listener& _listener, void DBusProxy::availabilityTimeoutThreadHandler() const { std::unique_lock threadLock(availabilityTimeoutThreadMutex_); - bool cancel = false; + bool finish = false; bool firstIteration = true; // the callbacks that have to be done are stored with @@ -63,7 +63,7 @@ void DBusProxy::availabilityTimeoutThreadHandler() const { > CallbackData_t; std::list callbacks; - while(!cancel) { + while(!cancelAvailabilityTimeoutThread_ && !finish) { //get min timeout timeoutsMutex_.lock(); @@ -175,7 +175,7 @@ void DBusProxy::availabilityTimeoutThreadHandler() const { //cancel thread timeoutsMutex_.lock(); if(timeouts_.size() == 0 && callbacks.size() == 0) - cancel = true; + finish = true; timeoutsMutex_.unlock(); } } @@ -187,7 +187,8 @@ DBusProxy::DBusProxy(const DBusAddress &_dbusAddress, availabilityStatus_(AvailabilityStatus::UNKNOWN), interfaceVersionAttribute_(*this, "uu", "getInterfaceVersion"), dbusServiceRegistry_(DBusServiceRegistry::get(_connection)), - everAvailable_(false) + everAvailable_(false), + cancelAvailabilityTimeoutThread_(false) { } @@ -200,6 +201,11 @@ void DBusProxy::init() { } DBusProxy::~DBusProxy() { + cancelAvailabilityTimeoutThread_ = true; + { + std::lock_guard itsTimeoutThreadLock(availabilityTimeoutThreadMutex_); + availabilityTimeoutCondition_.notify_all(); + } if(availabilityTimeoutThread_) { if(availabilityTimeoutThread_->joinable()) availabilityTimeoutThread_->join(); diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 5ae19c9..3707379 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -70,10 +70,11 @@ set(ExtendedInterfaceDBusSources ${ExtendedInterfaceSources} src-gen/dbus/${VERSION}/commonapi/tests/ExtendedInterfaceDBusProxy.cpp src-gen/dbus/${VERSION}/commonapi/tests/ExtendedInterfaceDBusStubAdapter.cpp) - -set(TEST_LINK_LIBRARIES -Wl,--no-as-needed CommonAPI-DBus -Wl,--as-needed CommonAPI ${DBus_LDFLAGS} ${DL_LIBRARY} gtest ${PTHREAD_LIBRARY}) - -set(TEST_LINK_LIBRARIES_WITHOUT_COMMONAPI_DBUS CommonAPI gtest ${PTHREAD_LIBRARY}) +if (MSVC) + set(TEST_LINK_LIBRARIES ${DBus_LDFLAGS} CommonAPI-DBus CommonAPI gtest ) +else() + set(TEST_LINK_LIBRARIES -Wl,--no-as-needed CommonAPI-DBus -Wl,--as-needed CommonAPI ${DBus_LDFLAGS} ${DL_LIBRARY} gtest ${PTHREAD_LIBRARY}) +endif() ############################################################################## # DBusConnectionTest @@ -145,4 +146,3 @@ add_test(NAME DBusVariantOutputStreamTest COMMAND DBusVariantOutputStreamTest) add_test(NAME DBusDaemonProxyTest COMMAND DBusDaemonProxyTest) add_test(NAME DBusVariantTest COMMAND DBusVariantTest) add_test(NAME DBusClientIdTest COMMAND DBusClientIdTest) -