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

Fixed bug #6802 : When the statement timeout is set, it causes the lock manager to delay reporting deadlocks until timeout is expired

This commit is contained in:
hvlad 2021-05-14 20:43:50 +03:00
parent 4cd4649691
commit 0c02c039e4
4 changed files with 25 additions and 40 deletions

View File

@ -8657,7 +8657,7 @@ bool TimeoutTimer::expired() const
return false;
const SINT64 t = currTime();
return t > m_start + m_value;
return t >= m_start + m_value;
}
unsigned int TimeoutTimer::timeToExpire() const
@ -8838,6 +8838,24 @@ void thread_db::reschedule()
tdbb_quantum = (tdbb_flags & TDBB_sweeper) ? SWEEP_QUANTUM : QUANTUM;
}
SLONG thread_db::adjustWait(SLONG wait) const
{
if ((wait == 0) || (tdbb_flags & TDBB_wait_cancel_disable) || !tdbb_reqTimer)
return wait;
const unsigned int tout = tdbb_reqTimer->timeToExpire();
SLONG t;
if (tout < MAX_SSHORT * 1000)
t = (tout + 999) / 1000;
else
t = MAX_SSHORT;
if (wait > t)
return t;
return wait;
}
// end thread_db methods

View File

@ -655,6 +655,10 @@ public:
return tdbb_reqTimer;
}
// Returns minimum of passed wait timeout and time to expiration of reqTimer.
// Timer value is rounded to the upper whole second.
SLONG adjustWait(SLONG wait) const;
void registerBdb(BufferDesc* bdb)
{
if (tdbb_bdbs.isEmpty()) {

View File

@ -56,7 +56,6 @@
using namespace Jrd;
using namespace Firebird;
static SSHORT adjust_wait(thread_db* tdbb, SSHORT wait);
static void bug_lck(const TEXT*);
static bool compatible(const Lock*, const Lock*, USHORT);
static void enqueue(thread_db*, CheckStatusWrapper*, Lock*, USHORT, SSHORT);
@ -344,7 +343,6 @@ bool LCK_convert(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
WaitCancelGuard guard(tdbb, lock, wait);
FbLocalStatus statusVector;
wait = adjust_wait(tdbb, wait);
const bool result = CONVERT(tdbb, &statusVector, lock, level, wait);
if (!result)
@ -672,7 +670,6 @@ bool LCK_lock(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
WaitCancelGuard guard(tdbb, lock, wait);
FbLocalStatus statusVector;
wait = adjust_wait(tdbb, wait);
ENQUEUE(tdbb, &statusVector, lock, level, wait);
fb_assert(LCK_CHECK_LOCK(lock));
@ -872,40 +869,6 @@ void LCK_write_data(thread_db* tdbb, Lock* lock, LOCK_DATA_T data)
}
static SSHORT adjust_wait(thread_db* tdbb, SSHORT wait)
{
/**************************************
*
* a d j u s t _ w a i t
*
**************************************
*
* Functional description
* If wait is cancellable and if statement timer was started - calc new wait
* time to ensure it will not take longer than rest of timeout.
*
**************************************/
if ((wait == LCK_NO_WAIT) || (tdbb->tdbb_flags & TDBB_wait_cancel_disable) || !tdbb->getTimeoutTimer())
return wait;
unsigned int tout = tdbb->getTimeoutTimer()->timeToExpire();
if (tout > 0)
{
SSHORT t;
if (tout < 1000)
t = 1;
else if (tout < MAX_SSHORT * 1000)
t = (tout + 999) / 1000;
else
t = MAX_SSHORT;
if ((wait == LCK_WAIT) || (-wait > t))
return -t;
}
return wait;
}
static void bug_lck(const TEXT* string)
{
/**************************************

View File

@ -3765,7 +3765,7 @@ void LockManager::wait_for_request(thread_db* tdbb, lrq* request, SSHORT lck_wai
// out the time when the lock request will timeout
const time_t lock_timeout = (lck_wait < 0) ? current_time + (-lck_wait) : 0;
time_t deadlock_timeout = current_time + scan_interval;
time_t deadlock_timeout = current_time + tdbb->adjustWait(scan_interval);
// Wait in a loop until the lock becomes available
@ -3890,7 +3890,7 @@ void LockManager::wait_for_request(thread_db* tdbb, lrq* request, SSHORT lck_wai
// We're going to do some real work - reset when we next want to
// do a deadlock scan
deadlock_timeout = current_time + scan_interval;
deadlock_timeout = current_time + tdbb->adjustWait(scan_interval);
// Handle lock event first
if (ret == FB_SUCCESS)