From 957675f4a2b7ba4e96541c5a9747b60cbfab9175 Mon Sep 17 00:00:00 2001 From: Dmitry Yemanov Date: Wed, 4 Dec 2024 15:48:53 +0300 Subject: [PATCH] Cleanup batches inside the engine if they were not released explicitly before disconnection. This avoids a resource leak (it's mostly about TempSpace). --- src/dsql/DsqlBatch.cpp | 9 +++++++-- src/jrd/Attachment.cpp | 10 +++++++--- src/jrd/Attachment.h | 7 ++++--- src/jrd/jrd.cpp | 6 ++---- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/dsql/DsqlBatch.cpp b/src/dsql/DsqlBatch.cpp index a5fb6b0b9fe..7442f15305d 100644 --- a/src/dsql/DsqlBatch.cpp +++ b/src/dsql/DsqlBatch.cpp @@ -151,15 +151,20 @@ DsqlBatch::DsqlBatch(DsqlDmlRequest* req, const dsql_msg* /*message*/, IMessageM // assign initial default BPB setDefBpb(FB_NELEM(initBlobParameters), initBlobParameters); -} + if (const auto att = m_dsqlRequest->req_dbb->dbb_attachment) + att->registerBatch(this); +} DsqlBatch::~DsqlBatch() { if (m_batch) m_batch->resetHandle(); if (m_dsqlRequest) - m_dsqlRequest->req_batch = NULL; + m_dsqlRequest->req_batch = nullptr; + + if (const auto att = m_dsqlRequest->req_dbb->dbb_attachment) + att->deregisterBatch(this); } Attachment* DsqlBatch::getAttachment() const diff --git a/src/jrd/Attachment.cpp b/src/jrd/Attachment.cpp index 0638f01d59f..a30facf742e 100644 --- a/src/jrd/Attachment.cpp +++ b/src/jrd/Attachment.cpp @@ -47,6 +47,7 @@ #include "../jrd/replication/Applier.h" #include "../jrd/replication/Manager.h" +#include "../dsql/DsqlBatch.h" #include "../dsql/DsqlStatementCache.h" #include "../common/classes/fb_string.h" @@ -288,9 +289,6 @@ Jrd::Attachment::~Attachment() delete att_trace_manager; - for (unsigned n = 0; n < att_batches.getCount(); ++n) - att_batches[n]->resetHandle(); - for (Function** iter = att_functions.begin(); iter < att_functions.end(); ++iter) { Function* const function = *iter; @@ -449,6 +447,12 @@ void Jrd::Attachment::storeBinaryBlob(thread_db* tdbb, jrd_tra* transaction, blob->BLB_close(tdbb); } +void Jrd::Attachment::releaseBatches() +{ + while (att_batches.hasData()) + delete att_batches.pop(); +} + void Jrd::Attachment::releaseGTTs(thread_db* tdbb) { if (!att_relations) diff --git a/src/jrd/Attachment.h b/src/jrd/Attachment.h index 684c8d55339..c5cd453876c 100644 --- a/src/jrd/Attachment.h +++ b/src/jrd/Attachment.h @@ -734,6 +734,7 @@ class Attachment : public pool_alloc void storeBinaryBlob(thread_db* tdbb, jrd_tra* transaction, bid* blobId, const Firebird::ByteChunk& chunk); + void releaseBatches(); void releaseGTTs(thread_db* tdbb); void resetSession(thread_db* tdbb, jrd_tra** traHandle); @@ -796,12 +797,12 @@ class Attachment : public pool_alloc } // batches control - void registerBatch(JBatch* b) + void registerBatch(DsqlBatch* b) { att_batches.add(b); } - void deregisterBatch(JBatch* b) + void deregisterBatch(DsqlBatch* b) { att_batches.findAndRemove(b); } @@ -864,7 +865,7 @@ class Attachment : public pool_alloc unsigned int att_stmt_timeout; // milliseconds Firebird::RefPtr att_idle_timer; - Firebird::Array att_batches; + Firebird::Array att_batches; InitialOptions att_initial_options; // Initial session options DebugOptions att_debug_options; Firebird::AutoPtr att_profiler_manager; // ProfilerManager diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 8490f867f8c..0706bbeeb61 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -6070,7 +6070,6 @@ JBatch* JStatement::createBatch(Firebird::CheckStatusWrapper* status, Firebird:: batch = FB_NEW JBatch(dsqlBatch, this, inMetadata); batch->addRef(); dsqlBatch->setInterfacePtr(batch); - tdbb->getAttachment()->registerBatch(batch); } catch (const Exception& ex) { @@ -6146,9 +6145,6 @@ void JBatch::freeEngineData(Firebird::CheckStatusWrapper* user_status) try { - Attachment* att = getAttachment()->getHandle(); - if (att) - att->deregisterBatch(this); delete batch; batch = nullptr; } @@ -7726,6 +7722,8 @@ void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment, XThreadEns if (attachment->att_event_session) dbb->eventManager()->deleteSession(attachment->att_event_session); + attachment->releaseBatches(); + // CMP_release() changes att_requests. while (attachment->att_requests.hasData()) CMP_release(tdbb, attachment->att_requests.back());