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

Postfix for #7446: never attempt to delete savepoints belonging to a different transaction

This commit is contained in:
Dmitry Yemanov 2023-01-31 12:01:59 +03:00
parent 914fded635
commit 9dc3f5e6cc
2 changed files with 41 additions and 3 deletions

View File

@ -3712,6 +3712,7 @@ const StmtNode* InAutonomousTransactionNode::execute(thread_db* tdbb, jrd_req* r
org_transaction->tra_lock_timeout,
org_transaction);
request->pushTransaction(org_transaction);
TRA_attach_request(transaction, request);
tdbb->setTransaction(transaction);
@ -3722,12 +3723,13 @@ const StmtNode* InAutonomousTransactionNode::execute(thread_db* tdbb, jrd_req* r
}
catch (Exception&)
{
TRA_detach_request(request);
request->popTransaction();
TRA_attach_request(org_transaction, request);
tdbb->setTransaction(org_transaction);
throw;
}
request->req_auto_trans.push(org_transaction);
impure->traNumber = transaction->tra_number;
VIO_start_save_point(tdbb, transaction);
@ -3841,8 +3843,11 @@ const StmtNode* InAutonomousTransactionNode::execute(thread_db* tdbb, jrd_req* r
}
impure->traNumber = impure->savNumber = 0;
transaction = request->req_auto_trans.pop();
// Normally request is detached by commit/rollback, but they may fail.
// It should be done before request->popTransaction().
TRA_detach_request(request);
transaction = request->popTransaction();
TRA_attach_request(transaction, request);
tdbb->setTransaction(transaction);

View File

@ -164,6 +164,21 @@ private:
class jrd_req : public pool_alloc<type_req>
{
// Context data saved/restored with every new autonomous transaction
struct AutoTranCtx
{
AutoTranCtx() : m_transaction(NULL), m_savepoints(NULL)
{}
AutoTranCtx(jrd_tra* tran, Savepoint* save) :
m_transaction(tran), m_savepoints(save)
{}
jrd_tra* m_transaction;
Savepoint* m_savepoints;
};
public:
jrd_req(Attachment* attachment, /*const*/ JrdStatement* aStatement,
Firebird::MemoryStats* parent_stats)
@ -263,7 +278,7 @@ public:
ULONG req_src_column;
dsc* req_domain_validation; // Current VALUE for constraint validation
Firebird::Stack<jrd_tra*> req_auto_trans; // Autonomous transactions
Firebird::Stack<AutoTranCtx> req_auto_trans; // Autonomous transactions
SortOwner req_sorts;
Firebird::Array<record_param> req_rpb; // record parameter blocks
Firebird::Array<UCHAR> impureArea; // impure area
@ -294,6 +309,24 @@ public:
}
req_base_stats.assign(req_stats);
}
// Save context when switching to the autonomous transaction
void pushTransaction(jrd_tra* const transaction)
{
req_auto_trans.push(AutoTranCtx(transaction, req_proc_sav_point));
req_proc_sav_point = NULL;
}
// Restore context
jrd_tra* popTransaction()
{
fb_assert(!req_transaction); // must be detached
const AutoTranCtx tmp = req_auto_trans.pop();
req_proc_sav_point = tmp.m_savepoints;
return tmp.m_transaction;
}
};
// Flags for req_flags