From e49e483646f14a2e626190d5ef98f628668d025c Mon Sep 17 00:00:00 2001 From: Dilip Kumar Date: Thu, 12 Mar 2020 13:16:45 +0530 Subject: [PATCH v5] WIP-Add assert check for relation extension lock Add assert to check that we should not acquire any other lock if we are already holding the relation extension lock. Only exception is that if we are trying to acquire the relation extension lock then we can hold the same lock. --- src/backend/storage/lmgr/lock.c | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 56dba09..f572dab 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -170,6 +170,15 @@ typedef struct TwoPhaseLockRecord */ static int FastPathLocalUseCount = 0; +/* + * Flag is set if the relation extension lock is currently held by this backend. + * We need this flag so that we can ensure that while holding the relation + * extension lock we are not trying to acquire any other heavy weight lock. + * Basically, that will ensuring that the proc holding relation extension lock + * can not wait for any another lock which can lead to a deadlock. + */ +static bool IsRelationExtensionLockHeld = false; + /* Macros for manipulating proc->fpLockBits */ #define FAST_PATH_BITS_PER_SLOT 3 #define FAST_PATH_LOCKNUMBER_OFFSET 1 @@ -841,6 +850,14 @@ LockAcquireExtended(const LOCKTAG *locktag, } /* + * We should not try to acquire any other heavyweight lock if we are already + * holding the relation extension lock. If we are trying to hold the same + * relation extension lock then it should have been already granted so we + * will not come here. + */ + Assert(!IsRelationExtensionLockHeld); + + /* * Prepare to emit a WAL record if acquisition of this lock needs to be * replayed in a standby server. * @@ -900,6 +917,11 @@ LockAcquireExtended(const LOCKTAG *locktag, locallock->lock = NULL; locallock->proclock = NULL; GrantLockLocal(locallock, owner); + + /* Set the flag that we acquired the relation extension lock. */ + if (locktag->locktag_type == LOCKTAG_RELATION_EXTEND) + IsRelationExtensionLockHeld = true; + return LOCKACQUIRE_OK; } } @@ -1100,6 +1122,10 @@ LockAcquireExtended(const LOCKTAG *locktag, locktag->locktag_field2); } + /* Set the flag that we acquired the relation extension lock. */ + if (locktag->locktag_type == LOCKTAG_RELATION_EXTEND) + IsRelationExtensionLockHeld = true; + return LOCKACQUIRE_OK; } @@ -1999,6 +2025,13 @@ LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock) if (released) { RemoveLocalLock(locallock); + + /* + * Reset the flag if we have released the relation extension lock. + */ + if (locktag->locktag_type == LOCKTAG_RELATION_EXTEND) + IsRelationExtensionLockHeld = false; + return true; } } @@ -2072,6 +2105,10 @@ LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock) LWLockRelease(partitionLock); RemoveLocalLock(locallock); + + /* Reset the flag if we have released the relation extension lock. */ + if (locktag->locktag_type == LOCKTAG_RELATION_EXTEND) + IsRelationExtensionLockHeld = false; return true; } @@ -2347,6 +2384,12 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks) LWLockRelease(partitionLock); } /* loop over partitions */ + /* + * We have released all the lock so reset the relation extension lock held + * flag. + */ + IsRelationExtensionLockHeld = false; + #ifdef LOCK_DEBUG if (*(lockMethodTable->trace_flag)) elog(LOG, "LockReleaseAll done"); -- 1.8.3.1