From 6a63c3bf47aa190138a696a1e524949eeba031c8 Mon Sep 17 00:00:00 2001 From: Alex Peshkoff Date: Fri, 7 Sep 2018 17:05:42 +0300 Subject: [PATCH] Backported CORE-5908: Enhance dynamic libraries loading related error messages --- src/common/os/darwin/mod_loader.cpp | 13 +++++-- src/common/os/mod_loader.h | 14 +++---- src/common/os/posix/mod_loader.cpp | 17 ++++++--- src/common/os/win32/mod_loader.cpp | 9 ++++- src/common/unicode_util.cpp | 6 +-- src/jrd/IntlManager.cpp | 9 +++-- src/jrd/flu.cpp | 2 +- src/jrd/fun.epp | 2 +- src/plugins/udr_engine/UdrEngine.cpp | 55 +++++++++++++--------------- src/remote/remote.cpp | 2 +- src/yvalve/PluginManager.cpp | 11 ++++-- 11 files changed, 79 insertions(+), 61 deletions(-) diff --git a/src/common/os/darwin/mod_loader.cpp b/src/common/os/darwin/mod_loader.cpp index b7b6acac09..1556d02cd6 100644 --- a/src/common/os/darwin/mod_loader.cpp +++ b/src/common/os/darwin/mod_loader.cpp @@ -87,14 +87,19 @@ void ModuleLoader::doctorModuleExtension(Firebird::PathName& name) #define FB_RTLD_MODE RTLD_LAZY #endif -ModuleLoader::Module* ModuleLoader::loadModule(const Firebird::PathName& modPath) +ModuleLoader::Module* ModuleLoader::loadModule(ISC_STATUS* status, const Firebird::PathName& modPath) { void* module = dlopen(modPath.c_str(), FB_RTLD_MODE); if (module == NULL) { -#ifdef DEBUG_LOADER - fprintf(stderr, "load error: %s: %s\n", modPath.c_str(), dlerror()); -#endif // DEBUG_LOADER + if (status) + { + status[0] = isc_arg_gds; + status[1] = isc_random; + status[2] = isc_arg_string; + status[3] = (ISC_STATUS) dlerror(); + status[4] = isc_arg_end; + } return 0; } diff --git a/src/common/os/mod_loader.h b/src/common/os/mod_loader.h index b57af4ac9f..069ab23039 100644 --- a/src/common/os/mod_loader.h +++ b/src/common/os/mod_loader.h @@ -90,11 +90,11 @@ class ModuleLoader /** loadModule is given as a string the path to the module to load. It attempts to load the module. If successful it returns the ModuleLoader::Module object that represents the loaded module in memory and can be used to - perform symbol lookups on the module. If unsuccessful it returns NULL. - It is the callers responsibility to delete the returned module object - when it is no longer needed. + perform symbol lookups on the module. It is the callers responsibility to delete + the returned module object when it is no longer needed. + If unsuccessful it returns NULL. OS-specific error is returned in status parameter. **/ - static Module* loadModule(const Firebird::PathName&); + static Module* loadModule(ISC_STATUS* status, const Firebird::PathName&); /** doctorModuleExtension modifies the given path name to add the platform specific module extention. This allows the user to provide the root name @@ -107,14 +107,14 @@ class ModuleLoader /** Almost like loadModule(), but in case of failure invokes doctorModuleExtension() and retries. **/ - static Module* fixAndLoadModule(const Firebird::PathName& modName) + static Module* fixAndLoadModule(ISC_STATUS* status, const Firebird::PathName& modName) { - Module* mod = loadModule(modName); + Module* mod = loadModule(NULL, modName); if (!mod) { Firebird::PathName fixed(modName); doctorModuleExtension(fixed); - mod = loadModule(fixed); + mod = loadModule(status, fixed); } return mod; } diff --git a/src/common/os/posix/mod_loader.cpp b/src/common/os/posix/mod_loader.cpp index 2b42c59a5c..9c8ba38ddd 100644 --- a/src/common/os/posix/mod_loader.cpp +++ b/src/common/os/posix/mod_loader.cpp @@ -72,7 +72,9 @@ void ModuleLoader::doctorModuleExtension(Firebird::PathName& name) Firebird::PathName::size_type pos = name.rfind("." SHRLIB_EXT); if (pos != name.length() - 3) { - name += "." SHRLIB_EXT; + pos = name.rfind("." SHRLIB_EXT "."); + if (pos == Firebird::PathName::npos) + name += "." SHRLIB_EXT; } pos = name.rfind('/'); pos = (pos == Firebird::PathName::npos) ? 0 : pos + 1; @@ -88,14 +90,19 @@ void ModuleLoader::doctorModuleExtension(Firebird::PathName& name) #define FB_RTLD_MODE RTLD_LAZY // save time when loading library #endif -ModuleLoader::Module* ModuleLoader::loadModule(const Firebird::PathName& modPath) +ModuleLoader::Module* ModuleLoader::loadModule(ISC_STATUS* status, const Firebird::PathName& modPath) { void* module = dlopen(modPath.nullStr(), FB_RTLD_MODE); if (module == NULL) { -#ifdef DEV_BUILD -// gds__log("loadModule failed loading %s: %s", modPath.c_str(), dlerror()); -#endif + if (status) + { + status[0] = isc_arg_gds; + status[1] = isc_random; + status[2] = isc_arg_string; + status[3] = (ISC_STATUS) dlerror(); + status[4] = isc_arg_end; + } return 0; } diff --git a/src/common/os/win32/mod_loader.cpp b/src/common/os/win32/mod_loader.cpp index 909de85026..2ffdbdfbeb 100644 --- a/src/common/os/win32/mod_loader.cpp +++ b/src/common/os/win32/mod_loader.cpp @@ -191,7 +191,7 @@ void ModuleLoader::doctorModuleExtension(PathName& name) name += ".dll"; } -ModuleLoader::Module* ModuleLoader::loadModule(const PathName& modPath) +ModuleLoader::Module* ModuleLoader::loadModule(ISC_STATUS* status, const PathName& modPath) { ContextActivator ctx; @@ -214,6 +214,13 @@ ModuleLoader::Module* ModuleLoader::loadModule(const PathName& modPath) if (!module) module = LoadLibraryEx(modPath.c_str(), 0, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!module && status) + { + status[0] = isc_arg_win32; + status[1] = GetLastError(); + status[2] = isc_arg_end; + } + // Restore old mode in case we are embedded into user application SetErrorMode(oldErrorMode); diff --git a/src/common/unicode_util.cpp b/src/common/unicode_util.cpp index 1850ea2e96..a33f495910 100644 --- a/src/common/unicode_util.cpp +++ b/src/common/unicode_util.cpp @@ -233,7 +233,7 @@ class ImplementConversionICU : public UnicodeUtil::ConversionICU, BaseICU PathName filename; formatFilename(filename, ucTemplate, aMajorVersion, aMinorVersion); - module = ModuleLoader::fixAndLoadModule(filename); + module = ModuleLoader::fixAndLoadModule(NULL, filename); if (!module) return; @@ -998,7 +998,7 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c icu = FB_NEW_POOL(*getDefaultMemoryPool()) ICU(majorVersion, minorVersion); - icu->ucModule = ModuleLoader::fixAndLoadModule(filename); + icu->ucModule = ModuleLoader::fixAndLoadModule(NULL, filename); if (!icu->ucModule) { @@ -1009,7 +1009,7 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c formatFilename(filename, inTemplate, majorVersion, minorVersion); - icu->inModule = ModuleLoader::fixAndLoadModule(filename); + icu->inModule = ModuleLoader::fixAndLoadModule(NULL, filename); if (!icu->inModule) { diff --git a/src/jrd/IntlManager.cpp b/src/jrd/IntlManager.cpp index b3e37afb61..4c8368ed22 100644 --- a/src/jrd/IntlManager.cpp +++ b/src/jrd/IntlManager.cpp @@ -471,15 +471,16 @@ bool IntlManager::initialize() ModuleLoader::Module* mod = NULL; bool exists = modules->exist(filename); + ISC_STATUS_ARRAY status; if (!exists) { - mod = ModuleLoader::loadModule(filename); + mod = ModuleLoader::loadModule(status, filename); if (!mod) { ModuleLoader::doctorModuleExtension(filename); exists = modules->exist(filename); if (!exists) - mod = ModuleLoader::loadModule(filename); + mod = ModuleLoader::loadModule(status, filename); } } @@ -512,8 +513,8 @@ bool IntlManager::initialize() } else { - gds__log((string("Can't load INTL module '") + - filename.c_str() + "'").c_str()); + iscLogStatus((string("Can't load INTL module '") + + filename.c_str() + "'").c_str(), status); ok = false; } } diff --git a/src/jrd/flu.cpp b/src/jrd/flu.cpp index c0b9c453a0..e8a5bd7878 100644 --- a/src/jrd/flu.cpp +++ b/src/jrd/flu.cpp @@ -245,7 +245,7 @@ namespace Jrd Arg::Str(initialModule)); } - ModuleLoader::Module* mlm = ModuleLoader::loadModule(fixedModule); + ModuleLoader::Module* mlm = ModuleLoader::loadModule(NULL, fixedModule); if (mlm) { im = FB_NEW_POOL(*getDefaultMemoryPool()) diff --git a/src/jrd/fun.epp b/src/jrd/fun.epp index ca964be72b..44fd5dde67 100644 --- a/src/jrd/fun.epp +++ b/src/jrd/fun.epp @@ -105,7 +105,7 @@ namespace { ModuleLoader::doctorModuleExtension(libName); - ModuleLoader::Module* module = ModuleLoader::loadModule(libName); + ModuleLoader::Module* module = ModuleLoader::loadModule(NULL, libName); if (!module) { message.printf("%s library has not been found", libName.c_str()); diff --git a/src/plugins/udr_engine/UdrEngine.cpp b/src/plugins/udr_engine/UdrEngine.cpp index 9c64ebee9a..a49ecf4120 100644 --- a/src/plugins/udr_engine/UdrEngine.cpp +++ b/src/plugins/udr_engine/UdrEngine.cpp @@ -567,47 +567,42 @@ UdrPluginImpl* Engine::loadModule(ThrowStatusWrapper* status, IRoutineMetadata* PathName path; PathUtils::concatPath(path, *i, *moduleName); - ModuleLoader::Module* module = ModuleLoader::fixAndLoadModule(path); - - if (module) - { - FB_BOOLEAN* (*entryPoint)(IStatus*, FB_BOOLEAN*, IUdrPlugin*); - - if (!module->findSymbol(STRINGIZE(FB_UDR_PLUGIN_ENTRY_POINT), entryPoint)) - { - static const ISC_STATUS statusVector[] = { - isc_arg_gds, isc_random, - isc_arg_string, (ISC_STATUS) "UDR plugin entry point not found", - isc_arg_end - }; + static ISC_STATUS_ARRAY statusArray = { + isc_arg_gds, isc_random, + isc_arg_string, (ISC_STATUS) "UDR module not loaded", + isc_arg_end + }; + const unsigned ARG_END = 4; - throw FbException(status, statusVector); - } + ModuleLoader::Module* module = ModuleLoader::fixAndLoadModule(&statusArray[ARG_END], path); + if (!module) + throw FbException(status, statusArray); - UdrPluginImpl* udrPlugin = FB_NEW UdrPluginImpl(*moduleName, module); - udrPlugin->theirUnloadFlag = entryPoint(status, &udrPlugin->myUnloadFlag, udrPlugin); + FB_BOOLEAN* (*entryPoint)(IStatus*, FB_BOOLEAN*, IUdrPlugin*); - if (status->getState() & IStatus::STATE_ERRORS) - { - delete udrPlugin; - ThrowStatusWrapper::checkException(status); - } - - modules->put(*moduleName, udrPlugin); - - return udrPlugin; - } - else + if (!module->findSymbol(STRINGIZE(FB_UDR_PLUGIN_ENTRY_POINT), entryPoint)) { static const ISC_STATUS statusVector[] = { isc_arg_gds, isc_random, - isc_arg_string, (ISC_STATUS) "Module not found", - //// TODO: isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) moduleName->c_str(), + isc_arg_string, (ISC_STATUS) "UDR plugin entry point not found", isc_arg_end }; throw FbException(status, statusVector); } + + UdrPluginImpl* udrPlugin = FB_NEW UdrPluginImpl(*moduleName, module); + udrPlugin->theirUnloadFlag = entryPoint(status, &udrPlugin->myUnloadFlag, udrPlugin); + + if (status->getState() & IStatus::STATE_ERRORS) + { + delete udrPlugin; + ThrowStatusWrapper::checkException(status); + } + + modules->put(*moduleName, udrPlugin); + + return udrPlugin; } static const ISC_STATUS statusVector[] = { diff --git a/src/remote/remote.cpp b/src/remote/remote.cpp index 9b99080c0c..dc2bc0c9bc 100644 --- a/src/remote/remote.cpp +++ b/src/remote/remote.cpp @@ -1335,7 +1335,7 @@ namespace { #else const char* name = "libz." SHRLIB_EXT ".1"; #endif - z.reset(ModuleLoader::fixAndLoadModule(name)); + z.reset(ModuleLoader::fixAndLoadModule(NULL, name)); if (z) symbols(); } diff --git a/src/yvalve/PluginManager.cpp b/src/yvalve/PluginManager.cpp index b0067a0c36..2875f62983 100644 --- a/src/yvalve/PluginManager.cpp +++ b/src/yvalve/PluginManager.cpp @@ -928,24 +928,27 @@ namespace RefPtr PluginSet::loadModule(const PluginLoadInfo& info) { PathName fixedModuleName(info.curModule); + ISC_STATUS_ARRAY statusArray; - ModuleLoader::Module* module = ModuleLoader::loadModule(fixedModuleName); + ModuleLoader::Module* module = ModuleLoader::loadModule(statusArray, fixedModuleName); if (!module && !ModuleLoader::isLoadableModule(fixedModuleName)) { ModuleLoader::doctorModuleExtension(fixedModuleName); - module = ModuleLoader::loadModule(fixedModuleName); + module = ModuleLoader::loadModule(statusArray, fixedModuleName); } if (!module) { if (ModuleLoader::isLoadableModule(fixedModuleName)) { - loadError(Arg::Gds(isc_pman_module_bad) << fixedModuleName); + loadError(Arg::Gds(isc_pman_module_bad) << fixedModuleName << + Arg::StatusVector(statusArray)); } if (info.required) { - loadError(Arg::Gds(isc_pman_module_notfound) << fixedModuleName); + loadError(Arg::Gds(isc_pman_module_notfound) << fixedModuleName << + Arg::StatusVector(statusArray)); } return RefPtr(NULL); From 4df43606a293ff3a9a6883a638b4559375449055 Mon Sep 17 00:00:00 2001 From: AlexPeshkoff Date: Tue, 18 Sep 2018 10:33:18 +0300 Subject: [PATCH] Backported CORE-5764: Installation of Firebird 3.0.3 on SLES 12 SP3 fails with "Could not find acceptable ICU library" --- src/common/unicode_util.cpp | 75 +++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/src/common/unicode_util.cpp b/src/common/unicode_util.cpp index a33f495910..d24eba9432 100644 --- a/src/common/unicode_util.cpp +++ b/src/common/unicode_util.cpp @@ -50,9 +50,6 @@ # include #endif -// The next major ICU version after 4.8 is 49. -#define ICU_NEW_VERSION_MEANING 49 - using namespace Firebird; @@ -122,7 +119,7 @@ struct BaseICU namespace Jrd { -static void formatFilename(PathName& filename, const char* templateName, +static ModuleLoader::Module* formatAndLoad(const char* templateName, int majorVersion, int minorVersion); @@ -230,10 +227,7 @@ class ImplementConversionICU : public UnicodeUtil::ConversionICU, BaseICU ImplementConversionICU(int aMajorVersion, int aMinorVersion) : BaseICU(aMajorVersion, aMinorVersion) { - PathName filename; - formatFilename(filename, ucTemplate, aMajorVersion, aMinorVersion); - - module = ModuleLoader::fixAndLoadModule(NULL, filename); + module = formatAndLoad(ucTemplate, aMajorVersion, aMinorVersion); if (!module) return; @@ -343,16 +337,27 @@ static const char* const COLL_30_VERSION = "41.128.4.4"; // ICU 3.0 collator ver static GlobalPtr icuModules; -static void formatFilename(PathName& filename, const char* templateName, +static ModuleLoader::Module* formatAndLoad(const char* templateName, int majorVersion, int minorVersion) { - string s; - if (majorVersion >= ICU_NEW_VERSION_MEANING) - s.printf("%d", majorVersion); - else - s.printf("%d%d", majorVersion, minorVersion); + // ICU has several schemas for placing version into file name + const char* patterns[] = + { + "%d", "%d_%d", "%d%d", NULL + }; + + PathName s, filename; + for (const char** p = patterns; *p; ++p) + { + s.printf(*p, majorVersion, minorVersion); + filename.printf(templateName, s.c_str()); - filename.printf(templateName, s.c_str()); + ModuleLoader::Module* module = ModuleLoader::fixAndLoadModule(NULL, filename); + if (module) + return module; + } + + return NULL; } @@ -975,17 +980,14 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c continue; string configVersion; - - if (majorVersion >= ICU_NEW_VERSION_MEANING) + configVersion.printf("%d.%d", majorVersion, minorVersion); + if (version != configVersion) { minorVersion = 0; configVersion.printf("%d", majorVersion); + if (version != configVersion) + continue; } - else - configVersion.printf("%d.%d", majorVersion, minorVersion); - - if (version != configVersion) - continue; ReadLockGuard readGuard(icuModules->lock, "UnicodeUtil::loadICU"); @@ -993,27 +995,19 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c if (icuModules->modules.get(version, icu)) return icu; - PathName filename; - formatFilename(filename, ucTemplate, majorVersion, minorVersion); - icu = FB_NEW_POOL(*getDefaultMemoryPool()) ICU(majorVersion, minorVersion); - - icu->ucModule = ModuleLoader::fixAndLoadModule(NULL, filename); - + icu->ucModule = formatAndLoad(ucTemplate, majorVersion, minorVersion); if (!icu->ucModule) { - gds__log("failed to load module %s", filename.c_str()); + gds__log("failed to load UC icu module version %s", configVersion.c_str()); delete icu; continue; } - formatFilename(filename, inTemplate, majorVersion, minorVersion); - - icu->inModule = ModuleLoader::fixAndLoadModule(NULL, filename); - + icu->inModule = formatAndLoad(inTemplate, majorVersion, minorVersion); if (!icu->inModule) { - gds__log("failed to load module %s", filename.c_str()); + gds__log("failed to load IN icu module version %s", configVersion.c_str()); delete icu; continue; } @@ -1138,26 +1132,25 @@ UnicodeUtil::ConversionICU& UnicodeUtil::getConversionICU() LocalStatus ls; CheckStatusWrapper lastError(&ls); string version; - const int majorArray[] = {5, 4, 3, 6, 0}; - for (const int* major = majorArray; *major; ++major) + for (int major = 4; major <= 79; ++major) { for (int minor = 20; minor--; ) // from 19 down to 0 { - if ((*major == favMaj) && (minor == favMin)) + if ((major == favMaj) && (minor == favMin)) { continue; } try { - if ((convIcu = ImplementConversionICU::create(*major, minor))) + if ((convIcu = ImplementConversionICU::create(major, minor))) return *convIcu; } catch (const Exception& ex) { ex.stuffException(&lastError); - version.printf("Error loading ICU library version %d.%d", *major, minor); + version.printf("Error loading ICU library version %d.%d", major, minor); } } } @@ -1180,7 +1173,7 @@ string UnicodeUtil::getDefaultIcuVersion() string rc; UnicodeUtil::ConversionICU& icu(UnicodeUtil::getConversionICU()); - if (icu.vMajor >= ICU_NEW_VERSION_MEANING) + if (icu.vMajor >= 10 && icu.vMinor == 0) rc.printf("%d", icu.vMajor); else rc.printf("%d.%d", icu.vMajor, icu.vMinor); @@ -1425,7 +1418,7 @@ USHORT UnicodeUtil::Utf16Collation::stringToKey(USHORT srcLen, const USHORT* src UErrorCode status = U_ZERO_ERROR; int len = icu->usetGetItem(contractions, i, NULL, NULL, str, sizeof(str), &status); - if (len > srcLenLong) + if (len > SLONG(srcLenLong)) len = srcLenLong; else --len;