Skip to content

Commit

Permalink
Backported CORE-5908: Enhance dynamic libraries loading related error…
Browse files Browse the repository at this point in the history
… messages
  • Loading branch information
AlexPeshkoff committed Sep 7, 2018
1 parent 2ec1e1e commit 6a63c3b
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 61 deletions.
13 changes: 9 additions & 4 deletions src/common/os/darwin/mod_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)

This comment has been minimized.

Copy link
@aafemt

aafemt Oct 12, 2018

Contributor

I wonder why ISC_STATUS* is used here instead of IStatus*.

This comment has been minimized.

Copy link
@AlexPeshkoff

AlexPeshkoff via email Oct 12, 2018

Author Member

This comment has been minimized.

Copy link
@aafemt

aafemt Oct 12, 2018

Contributor

But it prevent this function from being called with usage of LocalStatus or from any plugin implementation that has IStatus* as a parameter.

This comment has been minimized.

Copy link
@AlexPeshkoff

AlexPeshkoff via email Oct 12, 2018

Author Member
{
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;
}

Expand Down
14 changes: 7 additions & 7 deletions src/common/os/mod_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
Expand Down
17 changes: 12 additions & 5 deletions src/common/os/posix/mod_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down
9 changes: 8 additions & 1 deletion src/common/os/win32/mod_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);

Expand Down
6 changes: 3 additions & 3 deletions src/common/unicode_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)
{
Expand All @@ -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)
{
Expand Down
9 changes: 5 additions & 4 deletions src/jrd/IntlManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/jrd/flu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
2 changes: 1 addition & 1 deletion src/jrd/fun.epp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
55 changes: 25 additions & 30 deletions src/plugins/udr_engine/UdrEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
Expand Down
2 changes: 1 addition & 1 deletion src/remote/remote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
11 changes: 7 additions & 4 deletions src/yvalve/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -928,24 +928,27 @@ namespace
RefPtr<PluginModule> 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<PluginModule>(NULL);
Expand Down

0 comments on commit 6a63c3b

Please sign in to comment.