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

Fix for #8077: Error "Too many recursion levels" does not stop execuition of code that uses ON DISCONNECT trigger (PR#8119)

Co-authored-by: Vlad Khorsun <hvlad@users.sourceforge.net>
This commit is contained in:
Alexander Peshkov 2024-05-23 12:54:00 +03:00 committed by GitHub
parent 995dd02b3a
commit 7a4bbedf31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 63 additions and 5 deletions

View File

@ -212,6 +212,14 @@ void StatusVector::ImplStatusVector::append(const StatusVector& v) noexcept
void StatusVector::ImplStatusVector::prepend(const StatusVector& v) noexcept
{
auto errFrom = v.implementation->value();
auto lenFrom = v.implementation->firstWarning() ? v.implementation->firstWarning() : v.implementation->length();
auto errTo = value();
auto lenTo = firstWarning() ? firstWarning() : length();
if (lenFrom < lenTo && fb_utils::cmpStatus(lenFrom, errFrom, errTo))
return; // already here - ToDo: check warnings
ImplStatusVector newVector(getKind(), getCode());
if (newVector.appendErrors(v.implementation))

View File

@ -269,6 +269,12 @@ public:
*value |= oldValue;
}
void release(T cleanBit)
{
bit &= ~cleanBit;
oldValue &= ~cleanBit;
}
private:
// copying is prohibited
AutoSetRestoreFlag(const AutoSetRestoreFlag&);

View File

@ -602,6 +602,12 @@ void Jrd::Attachment::resetSession(thread_db* tdbb, jrd_tra** traHandle)
}
catch (const Exception& ex)
{
if (att_ext_call_depth && !shutAtt)
{
flags.release(ATT_resetting); // reset is incomplete - keep state
shutAtt = true;
}
if (shutAtt)
signalShutdown(isc_ses_reset_failed);

View File

@ -441,9 +441,9 @@ void Provider::jrdAttachmentEnd(thread_db* tdbb, Jrd::Attachment* att, bool forc
void Provider::releaseConnection(thread_db* tdbb, Connection& conn, bool inPool)
{
ConnectionsPool* connPool = conn.getConnPool();
Attachment* att = conn.getBoundAtt();
{ // m_mutex scope
Attachment* att = conn.getBoundAtt();
MutexLockGuard guard(m_mutex, FB_FUNCTION);
bool found = false;
@ -464,7 +464,42 @@ void Provider::releaseConnection(thread_db* tdbb, Connection& conn, bool inPool)
m_connections.add(AttToConn(NULL, &conn));
}
if (!inPool || !connPool || !connPool->getMaxCount() || !conn.isConnected() || !conn.resetSession(tdbb))
FbLocalStatus resetError;
inPool = inPool && connPool && connPool->getMaxCount() && conn.isConnected();
if (inPool)
{
inPool = conn.resetSession(tdbb);
// Check if reset of external session failed when parent (local) attachment
// is resetting or run ON DISCONNECT trigger.
const auto status = tdbb->tdbb_status_vector;
if (!inPool && status->hasData())
{
if (att->att_flags & ATT_resetting)
resetError.loadFrom(status);
else
{
auto req = tdbb->getRequest();
while (req)
{
if (req->req_trigger_action == TRIGGER_DISCONNECT)
{
resetError.loadFrom(status);
break;
}
req = req->req_caller;
}
}
}
}
if (inPool)
{
connPool->putConnection(tdbb, &conn);
}
else
{
{ // scope
MutexLockGuard guard(m_mutex, FB_FUNCTION);
@ -477,9 +512,8 @@ void Provider::releaseConnection(thread_db* tdbb, Connection& conn, bool inPool)
connPool->delConnection(tdbb, &conn, false);
Connection::deleteConnection(tdbb, &conn);
resetError.check();
}
else
connPool->putConnection(tdbb, &conn);
}
void Provider::clearConnections(thread_db* tdbb)

View File

@ -274,6 +274,7 @@ bool IscConnection::resetSession(thread_db* tdbb)
return true;
}
ERR_post_nothrow(&status);
return false;
}

View File

@ -8352,8 +8352,11 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign
const TrigVector* const trig_disconnect =
attachment->att_triggers[DB_TRIGGER_DISCONNECT];
// ATT_resetting may be set here only in a case when running on disconnect triggers
// in ALTER SESSION RESET already failed and attachment was shut down.
// Trying them once again here makes no sense.
if (!forcedPurge &&
!(attachment->att_flags & ATT_no_db_triggers) &&
!(attachment->att_flags & (ATT_no_db_triggers | ATT_resetting)) &&
trig_disconnect && !trig_disconnect->isEmpty())
{
ThreadStatusGuard temp_status(tdbb);