diff --git a/src/common/classes/ImplementHelper.h b/src/common/classes/ImplementHelper.h index cd2b28a128..34a7638977 100644 --- a/src/common/classes/ImplementHelper.h +++ b/src/common/classes/ImplementHelper.h @@ -313,7 +313,7 @@ public: typedef void VoidNoParam(); explicit UnloadDetectorHelper(MemoryPool&) - : cleanup(NULL), flagOsUnload(false) + : cleanup(NULL), thdDetach(NULL), flagOsUnload(false) { } void registerMe() @@ -348,6 +348,11 @@ public: cleanup = function; } + void setThreadDetach(VoidNoParam* function) + { + thdDetach = function; + } + void doClean() { flagOsUnload = false; @@ -359,8 +364,15 @@ public: } } + void threadDetach() + { + if (thdDetach) + thdDetach(); + } + private: VoidNoParam* cleanup; + VoidNoParam* thdDetach; bool flagOsUnload; }; diff --git a/src/include/firebird/FirebirdInterface.idl b/src/include/firebird/FirebirdInterface.idl index d35ba75599..5a7c78e944 100644 --- a/src/include/firebird/FirebirdInterface.idl +++ b/src/include/firebird/FirebirdInterface.idl @@ -213,6 +213,10 @@ interface PluginFactory : Versioned interface PluginModule : Versioned { void doClean(); + +version: // 3.0.3 => 3.0.4 + // Used to release resources allocated per-thread + void threadDetach(); } // Interface to deal with plugins here and there, returned by master interface diff --git a/src/include/firebird/IdlFbInterfaces.h b/src/include/firebird/IdlFbInterfaces.h index e9f879bd35..25ec6969e8 100644 --- a/src/include/firebird/IdlFbInterfaces.h +++ b/src/include/firebird/IdlFbInterfaces.h @@ -736,6 +736,7 @@ namespace Firebird struct VTable : public IVersioned::VTable { void (CLOOP_CARG *doClean)(IPluginModule* self) throw(); + void (CLOOP_CARG *threadDetach)(IPluginModule* self) throw(); }; protected: @@ -749,12 +750,21 @@ namespace Firebird } public: - static const unsigned VERSION = 2; + static const unsigned VERSION = 3; void doClean() { static_cast(this->cloopVTable)->doClean(this); } + + void threadDetach() + { + if (cloopVTable->version < 3) + { + return; + } + static_cast(this->cloopVTable)->threadDetach(this); + } }; class IPluginManager : public IVersioned @@ -7004,6 +7014,7 @@ namespace Firebird { this->version = Base::VERSION; this->doClean = &Name::cloopdoCleanDispatcher; + this->threadDetach = &Name::cloopthreadDetachDispatcher; } } vTable; @@ -7021,6 +7032,18 @@ namespace Firebird StatusType::catchException(0); } } + + static void CLOOP_CARG cloopthreadDetachDispatcher(IPluginModule* self) throw() + { + try + { + static_cast(self)->Name::threadDetach(); + } + catch (...) + { + StatusType::catchException(0); + } + } }; template > > @@ -7037,6 +7060,7 @@ namespace Firebird } virtual void doClean() = 0; + virtual void threadDetach() = 0; }; template diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index b8bd36655e..7961b353bf 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -426,9 +426,12 @@ static Static engineFactory; void registerEngine(IPluginManager* iPlugin) { - getUnloadDetector()->setCleanup(shutdownBeforeUnload); + UnloadDetectorHelper* module = getUnloadDetector(); + module->setCleanup(shutdownBeforeUnload); + module->setThreadDetach(threadDetach); + iPlugin->registerPluginFactory(IPluginManager::TYPE_PROVIDER, CURRENT_ENGINE, &engineFactory); - getUnloadDetector()->registerMe(); + module->registerMe(); } } // namespace Jrd diff --git a/src/yvalve/PluginManager.cpp b/src/yvalve/PluginManager.cpp index ee5c83622b..34dcf4543a 100644 --- a/src/yvalve/PluginManager.cpp +++ b/src/yvalve/PluginManager.cpp @@ -389,6 +389,14 @@ namespace } } + void threadDetach() + { + if (cleanup) + cleanup->threadDetach(); + if (next) + next->threadDetach(); + } + private: ~PluginModule() { @@ -492,8 +500,6 @@ namespace IPluginBase* factory(IFirebirdConf *iFirebirdConf); - ~ConfiguredPlugin(); - const char* getPlugName() { return plugName.c_str(); @@ -519,6 +525,8 @@ namespace int release(); private: + ~ConfiguredPlugin(); + RefPtr module; unsigned int regPlugin; RefPtr pluginLoaderConfig; @@ -682,6 +690,8 @@ namespace ConfiguredPlugin::~ConfiguredPlugin() { + MutexLockGuard g(plugins->mutex, FB_FUNCTION); + if (!destroyingPluginsMap) { plugins->remove(MapKey(module->getPlugin(regPlugin).type, plugName)); @@ -718,8 +728,6 @@ namespace int ConfiguredPlugin::release() { - MutexLockGuard g(plugins->mutex, FB_FUNCTION); - int x = --refCounter; #ifdef DEBUG_PLUGINS @@ -1172,6 +1180,13 @@ void PluginManager::waitForType(unsigned int typeThatMustGoAway) } } +void PluginManager::threadDetach() +{ + MutexLockGuard g(plugins->mutex, FB_FUNCTION); + modules->threadDetach(); +} + + } // namespace Firebird namespace { diff --git a/src/yvalve/PluginManager.h b/src/yvalve/PluginManager.h index 3d7052ae85..3b901a98a3 100644 --- a/src/yvalve/PluginManager.h +++ b/src/yvalve/PluginManager.h @@ -54,6 +54,7 @@ public: static void shutdown(); static void waitForType(unsigned int typeThatMustGoAway); + static void threadDetach(); }; } // namespace Firebird diff --git a/src/yvalve/utl.cpp b/src/yvalve/utl.cpp index 912210e649..b16b1a070b 100644 --- a/src/yvalve/utl.cpp +++ b/src/yvalve/utl.cpp @@ -56,6 +56,7 @@ #include "../yvalve/YObjects.h" #include "../yvalve/why_proto.h" #include "../yvalve/prepa_proto.h" +#include "../yvalve/PluginManager.h" #include "../jrd/constants.h" #include "../jrd/build_no.h" #include "../common/classes/ClumpletWriter.h" @@ -3172,6 +3173,7 @@ void ThreadCleanup::initThreadCleanup() void ThreadCleanup::finiThreadCleanup() { pthread_setspecific(key, NULL); + PluginManager::threadDetach(); } @@ -3204,6 +3206,7 @@ void ThreadCleanup::initThreadCleanup() void ThreadCleanup::finiThreadCleanup() { + PluginManager::threadDetach(); } #endif // #ifdef WIN_NT