mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:43:02 +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:
parent
995dd02b3a
commit
7a4bbedf31
@ -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))
|
||||
|
@ -269,6 +269,12 @@ public:
|
||||
*value |= oldValue;
|
||||
}
|
||||
|
||||
void release(T cleanBit)
|
||||
{
|
||||
bit &= ~cleanBit;
|
||||
oldValue &= ~cleanBit;
|
||||
}
|
||||
|
||||
private:
|
||||
// copying is prohibited
|
||||
AutoSetRestoreFlag(const AutoSetRestoreFlag&);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -274,6 +274,7 @@ bool IscConnection::resetSession(thread_db* tdbb)
|
||||
return true;
|
||||
}
|
||||
|
||||
ERR_post_nothrow(&status);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user