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

Fixed bug CORE-5681 : AV when external statement is executed and local transaction is rolled back

This commit is contained in:
hvlad 2017-12-17 02:05:00 +02:00
parent 40897c40de
commit 860f179712
2 changed files with 27 additions and 8 deletions

View File

@ -365,8 +365,24 @@ Transaction* Connection::createTransaction()
return tran;
}
void Connection::deleteTransaction(Transaction* tran)
void Connection::deleteTransaction(thread_db* tdbb, Transaction* tran)
{
// Close all active statements in tran context avoiding commit of already
// deleted transaction
Statement** stmt_ptr = m_statements.begin();
while (stmt_ptr < m_statements.end())
{
Statement* stmt = *stmt_ptr;
if (stmt->getTransaction() == tran)
{
if (stmt->isActive())
stmt->close(tdbb, true);
}
// close() above could destroy statement and remove it from m_statements
if (stmt_ptr < m_statements.end() && *stmt_ptr == stmt)
stmt_ptr++;
}
FB_SIZE_T pos;
if (m_transactions.find(tran, pos))
{
@ -378,7 +394,7 @@ void Connection::deleteTransaction(Transaction* tran)
}
if (!m_used_stmts && m_transactions.getCount() == 0 && !m_deleting)
m_provider.releaseConnection(JRD_get_thread_data(), *this);
m_provider.releaseConnection(tdbb, *this);
}
Statement* Connection::createStatement(const string& sql)
@ -657,7 +673,7 @@ void Transaction::commit(thread_db* tdbb, bool retain)
if (!retain)
{
detachFromJrdTran();
m_connection.deleteTransaction(this);
m_connection.deleteTransaction(tdbb, this);
}
}
@ -670,7 +686,7 @@ void Transaction::rollback(thread_db* tdbb, bool retain)
if (!retain)
{
detachFromJrdTran();
m_connection.deleteTransaction(this);
m_connection.deleteTransaction(tdbb, this);
}
if (status->getState() & IStatus::STATE_ERRORS) {
@ -710,7 +726,7 @@ Transaction* Transaction::getTransaction(thread_db* tdbb, Connection* conn, TraS
}
catch (const Exception&)
{
conn->deleteTransaction(ext_tran);
conn->deleteTransaction(tdbb, ext_tran);
throw;
}
}
@ -913,7 +929,7 @@ bool Statement::fetch(thread_db* tdbb, const ValueListNode* out_params)
return true;
}
void Statement::close(thread_db* tdbb)
void Statement::close(thread_db* tdbb, bool invalidTran)
{
// we must stuff exception if and only if this is the first time it occurs
// once we stuff exception we must punt
@ -942,6 +958,9 @@ void Statement::close(thread_db* tdbb)
unBindFromRequest();
}
if (invalidTran)
m_transaction = NULL;
if (m_transaction && m_transaction->getScope() == traAutonomous)
{
bool commitFailed = false;

View File

@ -201,7 +201,7 @@ public:
// transaction into m_transactions array and delete not needed transaction
// immediately (as we didn't pool transactions)
Transaction* createTransaction();
void deleteTransaction(Transaction* tran);
void deleteTransaction(Jrd::thread_db* tdbb, Transaction* tran);
// Statements management within connection scope : put newly created
// statement into m_statements array, but don't delete freed statement
@ -325,7 +325,7 @@ public:
void open(Jrd::thread_db* tdbb, Transaction* tran,
const Firebird::MetaName* const* in_names, const Jrd::ValueListNode* in_params, bool singleton);
bool fetch(Jrd::thread_db* tdbb, const Jrd::ValueListNode* out_params);
void close(Jrd::thread_db* tdbb);
void close(Jrd::thread_db* tdbb, bool invalidTran = false);
void deallocate(Jrd::thread_db* tdbb);
const Firebird::string& getSql() const { return m_sql; }