mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 04:03:04 +01:00
Better handling for the scratch pool and fixed CORE-5646.
CORE-5646 - Parse error when compiling a statement causes memory leak until attachment is disconnected.
This commit is contained in:
parent
0abddf94e0
commit
5e1b5e172e
@ -586,7 +586,7 @@ void DSQL_execute_immediate(thread_db* tdbb, Jrd::Attachment* attachment, jrd_tr
|
||||
}
|
||||
|
||||
|
||||
void DsqlDmlRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
|
||||
void DsqlDmlRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, bool* destroyScratchPool,
|
||||
ntrace_result_t* traceResult)
|
||||
{
|
||||
{ // scope
|
||||
@ -671,9 +671,9 @@ void DsqlDmlRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
|
||||
if (status)
|
||||
status_exception::raise(tdbb->tdbb_status_vector);
|
||||
|
||||
// Delete the scratch pool to reclaim memory.
|
||||
// We don't need the scratch pool anymore. Tell our caller to delete it.
|
||||
node = NULL;
|
||||
req_dbb->deletePool(&scratch->getPool());
|
||||
*destroyScratchPool = true;
|
||||
}
|
||||
|
||||
// Execute a dynamic SQL statement.
|
||||
@ -829,7 +829,7 @@ void DsqlDmlRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
|
||||
trace.finish(have_cursor, ITracePlugin::RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void DsqlDdlRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
|
||||
void DsqlDdlRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, bool* destroyScratchPool,
|
||||
ntrace_result_t* traceResult)
|
||||
{
|
||||
internalScratch = scratch;
|
||||
@ -914,7 +914,7 @@ void DsqlDdlRequest::rethrowDdlException(status_exception& ex, bool metadataUpda
|
||||
}
|
||||
|
||||
|
||||
void DsqlTransactionRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
|
||||
void DsqlTransactionRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, bool* destroyScratchPool,
|
||||
ntrace_result_t* /*traceResult*/)
|
||||
{
|
||||
node = Node::doDsqlPass(scratch, node);
|
||||
@ -933,7 +933,7 @@ void DsqlTransactionRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
|
||||
}
|
||||
|
||||
|
||||
void DsqlSessionManagementRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
|
||||
void DsqlSessionManagementRequest::dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, bool* destroyScratchPool,
|
||||
ntrace_result_t* /*traceResult*/)
|
||||
{
|
||||
node = Node::doDsqlPass(scratch, node);
|
||||
@ -1400,24 +1400,24 @@ static dsql_req* prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra*
|
||||
|
||||
// allocate the statement block, then prepare the statement
|
||||
|
||||
Jrd::ContextPoolHolder statementContext(tdbb, database->createPool());
|
||||
MemoryPool& statementPool = *tdbb->getDefaultPool();
|
||||
|
||||
DsqlCompiledStatement* statement = FB_NEW_POOL(statementPool) DsqlCompiledStatement(statementPool);
|
||||
|
||||
MemoryPool* scratchPool = database->createPool(&statementPool);
|
||||
|
||||
DsqlCompilerScratch* scratch = FB_NEW_POOL(*scratchPool) DsqlCompilerScratch(*scratchPool, database,
|
||||
transaction, statement);
|
||||
scratch->clientDialect = clientDialect;
|
||||
|
||||
if (isInternalRequest)
|
||||
scratch->flags |= DsqlCompilerScratch::FLAG_INTERNAL_REQUEST;
|
||||
|
||||
MemoryPool* statementPool = database->createPool();
|
||||
MemoryPool* scratchPool = NULL;
|
||||
dsql_req* request = NULL;
|
||||
|
||||
Jrd::ContextPoolHolder statementContext(tdbb, statementPool);
|
||||
try
|
||||
{
|
||||
DsqlCompiledStatement* statement = FB_NEW_POOL(*statementPool) DsqlCompiledStatement(*statementPool);
|
||||
|
||||
scratchPool = database->createPool();
|
||||
|
||||
DsqlCompilerScratch* scratch = FB_NEW_POOL(*scratchPool) DsqlCompilerScratch(*scratchPool, database,
|
||||
transaction, statement);
|
||||
scratch->clientDialect = clientDialect;
|
||||
|
||||
if (isInternalRequest)
|
||||
scratch->flags |= DsqlCompilerScratch::FLAG_INTERNAL_REQUEST;
|
||||
|
||||
string transformedText;
|
||||
|
||||
{ // scope to delete parser before the scratch pool is gone
|
||||
@ -1429,6 +1429,7 @@ static dsql_req* prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra*
|
||||
|
||||
// Parse the SQL statement. If it croaks, return
|
||||
request = parser.parse();
|
||||
request->liveScratchPool = scratchPool;
|
||||
|
||||
if (parser.isStmtAmbiguous())
|
||||
scratch->flags |= DsqlCompilerScratch::FLAG_AMBIGUOUS_STMT;
|
||||
@ -1473,12 +1474,12 @@ static dsql_req* prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra*
|
||||
transformedText.assign(temp.begin(), temp.getCount());
|
||||
}
|
||||
|
||||
statement->setSqlText(FB_NEW_POOL(statementPool) RefString(statementPool, transformedText));
|
||||
statement->setSqlText(FB_NEW_POOL(*statementPool) RefString(*statementPool, transformedText));
|
||||
|
||||
// allocate the send and receive messages
|
||||
|
||||
statement->setSendMsg(FB_NEW_POOL(statementPool) dsql_msg(statementPool));
|
||||
dsql_msg* message = FB_NEW_POOL(statementPool) dsql_msg(statementPool);
|
||||
statement->setSendMsg(FB_NEW_POOL(*statementPool) dsql_msg(*statementPool));
|
||||
dsql_msg* message = FB_NEW_POOL(*statementPool) dsql_msg(*statementPool);
|
||||
statement->setReceiveMsg(message);
|
||||
message->msg_number = 1;
|
||||
|
||||
@ -1490,7 +1491,14 @@ static dsql_req* prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra*
|
||||
ntrace_result_t traceResult = ITracePlugin::RESULT_SUCCESS;
|
||||
try
|
||||
{
|
||||
request->dsqlPass(tdbb, scratch, &traceResult);
|
||||
bool destroyScratchPool = false;
|
||||
request->dsqlPass(tdbb, scratch, &destroyScratchPool, &traceResult);
|
||||
|
||||
if (destroyScratchPool)
|
||||
{
|
||||
database->deletePool(scratchPool);
|
||||
request->liveScratchPool = scratchPool = NULL;
|
||||
}
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
@ -1510,6 +1518,14 @@ static dsql_req* prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra*
|
||||
request->req_traced = false;
|
||||
dsql_req::destroy(tdbb, request, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scratchPool)
|
||||
database->deletePool(scratchPool);
|
||||
|
||||
if (statementPool)
|
||||
database->deletePool(statementPool);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
@ -1577,6 +1593,7 @@ static void release_statement(DsqlCompiledStatement* statement)
|
||||
dsql_req::dsql_req(MemoryPool& pool)
|
||||
: req_pool(pool),
|
||||
statement(NULL),
|
||||
liveScratchPool(NULL),
|
||||
cursors(req_pool),
|
||||
req_dbb(NULL),
|
||||
req_transaction(NULL),
|
||||
@ -1772,7 +1789,12 @@ void dsql_req::destroy(thread_db* tdbb, dsql_req* request, bool drop)
|
||||
// Release the entire request if explicitly asked for
|
||||
|
||||
if (drop)
|
||||
{
|
||||
request->req_dbb->deletePool(&request->getPool());
|
||||
|
||||
if (request->liveScratchPool)
|
||||
request->req_dbb->deletePool(request->liveScratchPool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -163,9 +163,9 @@ public:
|
||||
|
||||
~dsql_dbb();
|
||||
|
||||
MemoryPool* createPool(MemoryPool* parent = NULL)
|
||||
MemoryPool* createPool()
|
||||
{
|
||||
return dbb_attachment->createPool(parent);
|
||||
return dbb_attachment->createPool();
|
||||
}
|
||||
|
||||
void deletePool(MemoryPool* pool)
|
||||
@ -490,8 +490,6 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
MemoryPool& getPool() { return PermanentStorage::getPool(); }
|
||||
|
||||
Type getType() const { return type; }
|
||||
void setType(Type value) { type = value; }
|
||||
|
||||
@ -573,7 +571,7 @@ public:
|
||||
return statement;
|
||||
}
|
||||
|
||||
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
|
||||
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, bool* destroyScratchPool,
|
||||
ntrace_result_t* traceResult) = 0;
|
||||
|
||||
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
|
||||
@ -611,6 +609,7 @@ private:
|
||||
|
||||
public:
|
||||
const DsqlCompiledStatement* statement;
|
||||
MemoryPool* liveScratchPool;
|
||||
Firebird::Array<DsqlCompiledStatement*> cursors; // Cursor update statements
|
||||
|
||||
dsql_dbb* req_dbb; // DSQL attachment
|
||||
@ -651,7 +650,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
|
||||
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, bool* destroyScratchPool,
|
||||
ntrace_result_t* traceResult);
|
||||
|
||||
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
|
||||
@ -681,7 +680,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
|
||||
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, bool* destroyScratchPool,
|
||||
ntrace_result_t* traceResult);
|
||||
|
||||
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
|
||||
@ -708,7 +707,7 @@ public:
|
||||
req_traced = false;
|
||||
}
|
||||
|
||||
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
|
||||
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, bool* destroyScratchPool,
|
||||
ntrace_result_t* traceResult);
|
||||
|
||||
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
|
||||
@ -730,7 +729,7 @@ public:
|
||||
req_traced = false;
|
||||
}
|
||||
|
||||
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch,
|
||||
virtual void dsqlPass(thread_db* tdbb, DsqlCompilerScratch* scratch, bool* destroyScratchPool,
|
||||
ntrace_result_t* traceResult);
|
||||
|
||||
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
|
||||
|
@ -111,11 +111,10 @@ void Jrd::Attachment::destroy(Attachment* const attachment)
|
||||
}
|
||||
|
||||
|
||||
MemoryPool* Jrd::Attachment::createPool(MemoryPool* parent)
|
||||
MemoryPool* Jrd::Attachment::createPool()
|
||||
{
|
||||
MemoryPool* const pool = MemoryPool::createPool(parent ? parent : att_pool, att_memory_stats);
|
||||
if (!parent)
|
||||
att_pools.add(pool);
|
||||
MemoryPool* const pool = MemoryPool::createPool(NULL, att_memory_stats);
|
||||
att_pools.add(pool);
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
@ -374,7 +374,7 @@ public:
|
||||
|
||||
Firebird::Array<MemoryPool*> att_pools; // pools
|
||||
|
||||
MemoryPool* createPool(MemoryPool* parent = NULL);
|
||||
MemoryPool* createPool();
|
||||
void deletePool(MemoryPool* pool);
|
||||
|
||||
/// former Database members - end
|
||||
|
Loading…
Reference in New Issue
Block a user