8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 23:23:04 +01:00

Postfix for #7418: Reliability of plugin manager; better error handling during plugin registration, removed limit on length of registration name

This commit is contained in:
AlexPeshkoff 2022-12-12 19:45:51 +03:00
parent 801bac7da0
commit 7ccbceead6

View File

@ -30,6 +30,7 @@
#include "../yvalve/why_proto.h" #include "../yvalve/why_proto.h"
#include "../common/os/path_utils.h" #include "../common/os/path_utils.h"
#include "../common/os/fbsyslog.h"
#include "../common/StatusArg.h" #include "../common/StatusArg.h"
#include "../common/isc_proto.h" #include "../common/isc_proto.h"
#include "../common/classes/fb_string.h" #include "../common/classes/fb_string.h"
@ -42,6 +43,8 @@
#include "../common/classes/GenericMap.h" #include "../common/classes/GenericMap.h"
#include "../common/db_alias.h" #include "../common/db_alias.h"
#include "../common/dllinst.h" #include "../common/dllinst.h"
#include "../common/file_params.h"
#include "../common/status.h"
#include "../yvalve/config/os/config_root.h" #include "../yvalve/config/os/config_root.h"
@ -246,8 +249,7 @@ namespace
IConfig* findPluginConfig(ConfigFile* pluginLoaderConfig, const PathName& confName) IConfig* findPluginConfig(ConfigFile* pluginLoaderConfig, const PathName& confName)
{ {
LocalStatus ls; FbLocalStatus ls;
CheckStatusWrapper s(&ls);
if (pluginLoaderConfig) if (pluginLoaderConfig)
{ {
@ -266,40 +268,39 @@ namespace
} }
} }
IConfig* rc = PluginManagerInterfacePtr()->getConfig(&s, confName.nullStr()); IConfig* rc = PluginManagerInterfacePtr()->getConfig(&ls, confName.nullStr());
check(&s); check(&ls);
return rc; return rc;
} }
// Plugins registered when loading plugin module. // Plugins registered when loading plugin module.
// This is POD object - no dtor, only simple data types inside.
struct RegisteredPlugin struct RegisteredPlugin
{ {
RegisteredPlugin(IPluginFactory* f, const char* nm, unsigned int t) RegisteredPlugin(IPluginFactory* f, const char* nm, unsigned int t)
: factory(f), type(t) : factory(f), name(nm), type(t)
{ }
RegisteredPlugin(MemoryPool& p, IPluginFactory* f, const char* nm, unsigned int t)
: factory(f), name(p), type(t)
{ {
if (nm) name = nm;
{
if (strlen(nm) >= sizeof(name))
{
fatal_exception::raiseFmt("Size of plugin registration name should not exceed %d bytes",
sizeof(name) - 1);
}
strcpy(name, nm);
}
else
name[0] = 0;
} }
RegisteredPlugin() RegisteredPlugin()
: factory(NULL), type(0) : factory(NULL), name(), type(0)
{ { }
name[0] = 0;
} RegisteredPlugin(MemoryPool& p)
: factory(NULL), name(p), type(0)
{ }
RegisteredPlugin(MemoryPool& p, const RegisteredPlugin& from)
: factory(from.factory), name(p, from.name), type(from.type)
{ }
IPluginFactory* factory; IPluginFactory* factory;
char name[32]; PathName name;
unsigned int type; unsigned int type;
}; };
@ -410,7 +411,7 @@ namespace
PathName name; PathName name;
Firebird::AutoPtr<ModuleLoader::Module> module; Firebird::AutoPtr<ModuleLoader::Module> module;
Firebird::IPluginModule* cleanup; Firebird::IPluginModule* cleanup;
HalfStaticArray<RegisteredPlugin, 2> regPlugins; ObjectsArray<RegisteredPlugin> regPlugins;
PluginModule* next; PluginModule* next;
PluginModule** prev; PluginModule** prev;
}; };
@ -589,9 +590,8 @@ namespace
fprintf(stderr, "~FactoryParameter places configuredPlugin %s in unload query for %d seconds\n", fprintf(stderr, "~FactoryParameter places configuredPlugin %s in unload query for %d seconds\n",
configuredPlugin->getPlugName(), configuredPlugin->getReleaseDelay() / 1000000); configuredPlugin->getPlugName(), configuredPlugin->getReleaseDelay() / 1000000);
#endif #endif
LocalStatus ls; FbLocalStatus ls;
CheckStatusWrapper s(&ls); TimerInterfacePtr()->start(&ls, configuredPlugin, configuredPlugin->getReleaseDelay());
TimerInterfacePtr()->start(&s, configuredPlugin, configuredPlugin->getReleaseDelay());
// errors are ignored here - configuredPlugin will be released at once // errors are ignored here - configuredPlugin will be released at once
} }
@ -604,18 +604,17 @@ namespace
FactoryParameter* par = FB_NEW FactoryParameter(this, firebirdConf); FactoryParameter* par = FB_NEW FactoryParameter(this, firebirdConf);
par->addRef(); par->addRef();
LocalStatus ls; FbLocalStatus ls;
CheckStatusWrapper s(&ls); IPluginBase* plugin = module->getPlugin(regPlugin).factory->createPlugin(&ls, par);
IPluginBase* plugin = module->getPlugin(regPlugin).factory->createPlugin(&s, par);
if (!(s.getState() & Firebird::IStatus::STATE_ERRORS)) if (!(ls->getState() & Firebird::IStatus::STATE_ERRORS))
{ {
plugin->setOwner(par); plugin->setOwner(par);
return plugin; return plugin;
} }
par->release(); par->release();
check(&s); check(&ls);
return NULL; return NULL;
} }
@ -826,8 +825,7 @@ namespace
{ {
namesList.assign(pnamesList); namesList.assign(pnamesList);
namesList.alltrim(" \t"); namesList.alltrim(" \t");
Firebird::LocalStatus s; FbLocalStatus statusWrapper;
Firebird::CheckStatusWrapper statusWrapper(&s);
next(&statusWrapper); next(&statusWrapper);
check(&statusWrapper); check(&statusWrapper);
} }
@ -1023,6 +1021,8 @@ PluginManager::PluginManager()
void PluginManager::registerPluginFactory(unsigned int interfaceType, const char* defaultName, IPluginFactory* factory) void PluginManager::registerPluginFactory(unsigned int interfaceType, const char* defaultName, IPluginFactory* factory)
{
try
{ {
MutexLockGuard g(plugins->mutex, FB_FUNCTION); MutexLockGuard g(plugins->mutex, FB_FUNCTION);
@ -1046,6 +1046,33 @@ void PluginManager::registerPluginFactory(unsigned int interfaceType, const char
plugins->put(MapKey(interfaceType, defaultName), p); plugins->put(MapKey(interfaceType, defaultName), p);
} }
} }
catch(const Exception& ex)
{
// looks like something gone seriously wrong - therefore add more error handling here
try
{
FbLocalStatus ls;
ex.stuffException(&ls);
char text[256];
UtilInterfacePtr()->formatStatus(text, sizeof(text), &ls);
Syslog::Record(Syslog::Error, text);
iscLogException("Plugin registration error", ex);
}
catch(const BadAlloc&)
{
Syslog::Record(Syslog::Error, "Plugin registration error - out of memory");
}
catch(...)
{
Syslog::Record(Syslog::Error, "Double fault during plugin registration");
}
#ifdef DEV_BUILD
abort();
#endif
}
}
void PluginManager::registerModule(IPluginModule* cleanup) void PluginManager::registerModule(IPluginModule* cleanup)