From cb33c616711c7e13b3a14123fbd41fa9dcb92f2a Mon Sep 17 00:00:00 2001 From: Philip Rauwolf Date: Fri, 23 Aug 2013 16:00:27 +0200 Subject: Fixed logic error in dynamic loading If an alias was defined for one binding that was equal to the well known name of another binding, the loading procedure that actually happened was inconsistent across different use cases and also did not match the description given in the README. --- src/CommonAPI/Runtime.cpp | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/CommonAPI/Runtime.cpp b/src/CommonAPI/Runtime.cpp index 83ef63d..a38556a 100644 --- a/src/CommonAPI/Runtime.cpp +++ b/src/CommonAPI/Runtime.cpp @@ -29,18 +29,22 @@ static const char COMMONAPI_LIB_PREFIX[] = "libCommonAPI-"; static const char MIDDLEWARE_INFO_SYMBOL_NAME[] = "middlewareInfo"; -inline bool Runtime::tryLoadLibrary(const std::string& libraryPath, void** sharedLibraryHandle, MiddlewareInfo** foundMiddlewareInfo) { +inline bool Runtime::tryLoadLibrary(const std::string& libraryPath, + void** sharedLibraryHandle, + MiddlewareInfo** foundMiddlewareInfo) { + //In case we find an already loaded library again while looking for another one, //there is no need to look at it if (dlopen(libraryPath.c_str(), RTLD_NOLOAD)) { return false; } + //In order to place symbols of the newly loaded library ahead of already resolved symbols, we need //RTLD_DEEPBIND. This is necessary for this case: A library already is linked at compile time, but while //trying to resolve another library dynamically we might find the very same library again. //dlopen() doesn't know about the compile time linked library and will close it if dlclose() ever is - //called, thereby causing memory corruptions and the like. Therefore, we must be able to access the - //middlewareInfo of the newly dlopened library in order to determine whether it already has been linked. + //called, thereby causing memory corruptions. Therefore, we must be able to access the middlewareInfo + //of the newly dlopened library in order to determine whether it already has been linked. *sharedLibraryHandle = dlopen(libraryPath.c_str(), RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND); if (sharedLibraryHandle == NULL) { return false; @@ -48,7 +52,7 @@ inline bool Runtime::tryLoadLibrary(const std::string& libraryPath, void** share *foundMiddlewareInfo = static_cast(dlsym(*sharedLibraryHandle, MIDDLEWARE_INFO_SYMBOL_NAME)); - //In this context, a resolved value of NULL it is just as invalid as if dlerror() was set. + //In this context, a resolved value of NULL it is just as invalid as if dlerror() was set additionally. if (!*foundMiddlewareInfo) { dlclose(*sharedLibraryHandle); return false; @@ -63,7 +67,10 @@ inline bool Runtime::tryLoadLibrary(const std::string& libraryPath, void** share } -bool Runtime::checkAndLoadLibrary(const std::string& libraryPath, const std::string& requestedBindingIdentifier, bool keepLibrary) { +bool Runtime::checkAndLoadLibrary(const std::string& libraryPath, + const std::string& requestedBindingIdentifier, + bool keepLibrary) { + void* sharedLibraryHandle = NULL; MiddlewareInfo* foundMiddlewareInfo; if (!tryLoadLibrary(libraryPath, &sharedLibraryHandle, &foundMiddlewareInfo)) { @@ -83,7 +90,7 @@ bool Runtime::checkAndLoadLibrary(const std::string& libraryPath, const std::str if (!keepLibrary) { dlclose(sharedLibraryHandle); } else { - //Extend visibility to make symbols available to all other libraries loaded afterwards, + //Extend visibility to make symbols available to all other libraries that are loaded afterwards, //e.g. libraries containing generated binding specific code. sharedLibraryHandle = dlopen(libraryPath.c_str(), RTLD_NOW | RTLD_GLOBAL); if (!sharedLibraryHandle) { @@ -214,7 +221,6 @@ std::shared_ptr Runtime::checkDynamicLibraries(const std::string& reque std::string versionString; LibraryVersion currentLibraryVersion = {-1, -1, -1}; - const char* fileNamePtr = fqnOfEntry.c_str(); while ((fileNamePtr = strchr(fileNamePtr + 1, '.'))) { if (strncmp(".so", fileNamePtr, 3) == 0) { @@ -266,11 +272,6 @@ std::shared_ptr Runtime::checkDynamicLibraries(const std::string& reque std::shared_ptr Runtime::checkDynamicLibraries(LoadState& loadState) { - const std::string& defaultBindingIdentifier = Configuration::getInstance().getDefaultMiddlewareIdentifier(); - if (defaultBindingIdentifier != "") { - return checkDynamicLibraries(defaultBindingIdentifier, loadState); - } - const std::vector& librarySearchPaths = Configuration::getInstance().getLibrarySearchPaths(); for (const std::string& singleSearchPath : librarySearchPaths) { @@ -318,13 +319,21 @@ std::shared_ptr Runtime::load(LoadState& loadState) { registeredRuntimeLoadFunctions_ = new std::unordered_map(); } - const auto defaultRuntimeLoader = registeredRuntimeLoadFunctions_->begin(); + const std::string& defaultBindingIdentifier = Configuration::getInstance().getDefaultMiddlewareIdentifier(); + if (defaultBindingIdentifier != "") { + const auto defaultRuntimeLoader = registeredRuntimeLoadFunctions_->find(defaultBindingIdentifier); + if (defaultRuntimeLoader != registeredRuntimeLoadFunctions_->end()) { + return (defaultRuntimeLoader->second)(); + } + return checkDynamicLibraries(defaultBindingIdentifier, loadState); - if (defaultRuntimeLoader != registeredRuntimeLoadFunctions_->end()) { - return (defaultRuntimeLoader->second)(); + } else { + const auto defaultRuntimeLoader = registeredRuntimeLoadFunctions_->begin(); + if (defaultRuntimeLoader != registeredRuntimeLoadFunctions_->end()) { + return (defaultRuntimeLoader->second)(); + } + return checkDynamicLibraries(loadState); } - - return checkDynamicLibraries(loadState); } -- cgit v1.2.1