diff --git a/src/jrd/Attachment.h b/src/jrd/Attachment.h index fd5873d43b..5b89720b9f 100644 --- a/src/jrd/Attachment.h +++ b/src/jrd/Attachment.h @@ -385,11 +385,7 @@ public: JAttachment* getInterface() throw(); - JProvider* getProvider() - { - fb_assert(att_provider); - return att_provider; - } + JProvider* getProvider(); private: Attachment(MemoryPool* pool, Database* dbb, JProvider* provider); @@ -461,6 +457,12 @@ inline bool Attachment::isUtility() const return (att_utility != UTIL_NONE); } +inline JProvider* Attachment::getProvider() +{ + fb_assert(att_provider || (att_flags & ATT_system)); + return att_provider; +} + // This class holds references to all attachments it contains class AttachmentsRefHolder diff --git a/src/jrd/ExtEngineManager.cpp b/src/jrd/ExtEngineManager.cpp index 468485d1e5..778bdb7ac2 100644 --- a/src/jrd/ExtEngineManager.cpp +++ b/src/jrd/ExtEngineManager.cpp @@ -603,8 +603,13 @@ ExtEngineManager::ExternalContextImpl::ExternalContextImpl(thread_db* tdbb, internalAttachment->getStable()->addRef(); - externalAttachment = MasterInterfacePtr()->registerAttachment - (internalAttachment->getProvider(), internalAttachment->getInterface()); + Jrd::JProvider* jProv = internalAttachment->getProvider(); + Jrd::JAttachment* jAtt = internalAttachment->getInterface(); + + // System attachments (such as garbage collector) have no external interface + // and should not be used by UDR's + if (jProv && jAtt) + externalAttachment = MasterInterfacePtr()->registerAttachment(jProv, jAtt); } ExtEngineManager::ExternalContextImpl::~ExternalContextImpl() @@ -616,6 +621,8 @@ ExtEngineManager::ExternalContextImpl::~ExternalContextImpl() externalAttachment->release(); externalAttachment = NULL; } + else + internalAttachment->getStable()->release(); } void ExtEngineManager::ExternalContextImpl::releaseTransaction() @@ -640,7 +647,10 @@ void ExtEngineManager::ExternalContextImpl::setTransaction(thread_db* tdbb) fb_assert(!externalTransaction && !internalTransaction); if ((internalTransaction = newTransaction)) - externalTransaction = MasterInterfacePtr()->registerTransaction(externalAttachment, internalTransaction); + { + if (externalAttachment) + externalTransaction = MasterInterfacePtr()->registerTransaction(externalAttachment, internalTransaction); + } } IMaster* ExtEngineManager::ExternalContextImpl::getMaster() @@ -657,6 +667,8 @@ IExternalEngine* ExtEngineManager::ExternalContextImpl::getEngine(CheckStatusWra Firebird::IAttachment* ExtEngineManager::ExternalContextImpl::getAttachment( CheckStatusWrapper* /*status*/) { + checkExternalAttachment(); + externalAttachment->addRef(); return externalAttachment; } @@ -664,6 +676,8 @@ Firebird::IAttachment* ExtEngineManager::ExternalContextImpl::getAttachment( Firebird::ITransaction* ExtEngineManager::ExternalContextImpl::getTransaction( CheckStatusWrapper* /*status*/) { + checkExternalAttachment(); + externalTransaction->addRef(); return externalTransaction; } @@ -703,6 +717,13 @@ void* ExtEngineManager::ExternalContextImpl::setInfo(int code, void* value) return oldValue; } +void ExtEngineManager::ExternalContextImpl::checkExternalAttachment() +{ + if (!externalAttachment) + { + (Arg::Gds(isc_random) << Arg::Str("Use of system attachment in UDR is not allowed")).raise(); + } +} //--------------------- diff --git a/src/jrd/ExtEngineManager.h b/src/jrd/ExtEngineManager.h index 683fd60ea9..c84494c89b 100644 --- a/src/jrd/ExtEngineManager.h +++ b/src/jrd/ExtEngineManager.h @@ -167,6 +167,8 @@ private: void* setInfo(int code, void* value); private: + void checkExternalAttachment(); + Firebird::IExternalEngine* engine; Attachment* internalAttachment; Firebird::ITransaction* internalTransaction; diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index a6b82a140f..363fc52e04 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -5091,6 +5091,7 @@ void Database::garbage_collector(Database* dbb) TRA_commit(tdbb, transaction, false); Monitoring::cleanupAttachment(tdbb); + dbb->dbb_extManager.closeAttachment(tdbb, attachment); attachment->releaseLocks(tdbb); LCK_fini(tdbb, LCK_OWNER_attachment);