[ 
https://issues.apache.org/jira/browse/IGNITE-29148?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Nikita Amelchev updated IGNITE-29148:
-------------------------------------
    Description: 
Fix explicit locks that stay held after unlock when a thread holds overlapping 
locks

If a thread holds several explicit locks with a common key and at least one of 
them is a multi-key lock (IgniteCache#lockAll), some keys may stay locked after 
all locks are released. Such a key blocks other locks and transactions on it 
until the locking node leaves the cluster, and can hang the next partition map 
exchange.

Cases, all in one thread, a = cache.lock(k1), b = cache.lockAll([k1, k2]):
1. a.lock(); b.lock(); b.unlock(); a.unlock() with k1 first in b: k2 stays 
locked. GridDhtColocatedCache#unlockAll takes the lock version from the reentry 
of k1, fails with "Failed to unlock (if keys were locked separately...)" and 
does not send the unlock request; the error is only logged.
2. a.lock(); b.lock(); a.unlock(); b.unlock(): k1 and k2 stay locked with the 
same error, because keys of one unlock have different lock versions.
3. Cases 1 and 2 with a near cache and k1, k2 on the same primary: a key stays 
locked silently, because GridNearTransactionalCache#unlockAll sends it under 
the lock version of another key.
4. a.lock(); b.tryLock(timeout) or b.tryLock() fails; a.unlock(): k1 stays 
locked silently. The rollback of b removes candidates by the version of b and 
keeps the reentry of k1, which has the version of a.
5. On a server node, with k1 primary on this node and first in b, followed by a 
key with a remote primary: a.lock(); b.lock(); b.unlock(); a.unlock() leaves k1 
locked silently, because of the same rollback in 
GridDhtColocatedLockFuture#mapAsPrimary.

The attached ExplicitLockReentryUnlockTest reproduces cases 1, 2 and 4.

> Fix explicit locks that stay held after unlock when a thread holds 
> overlapping locks
> ------------------------------------------------------------------------------------
>
>                 Key: IGNITE-29148
>                 URL: https://issues.apache.org/jira/browse/IGNITE-29148
>             Project: Ignite
>          Issue Type: Bug
>            Reporter: Nikita Amelchev
>            Priority: Major
>
> Fix explicit locks that stay held after unlock when a thread holds 
> overlapping locks
> If a thread holds several explicit locks with a common key and at least one 
> of them is a multi-key lock (IgniteCache#lockAll), some keys may stay locked 
> after all locks are released. Such a key blocks other locks and transactions 
> on it until the locking node leaves the cluster, and can hang the next 
> partition map exchange.
> Cases, all in one thread, a = cache.lock(k1), b = cache.lockAll([k1, k2]):
> 1. a.lock(); b.lock(); b.unlock(); a.unlock() with k1 first in b: k2 stays 
> locked. GridDhtColocatedCache#unlockAll takes the lock version from the 
> reentry of k1, fails with "Failed to unlock (if keys were locked 
> separately...)" and does not send the unlock request; the error is only 
> logged.
> 2. a.lock(); b.lock(); a.unlock(); b.unlock(): k1 and k2 stay locked with the 
> same error, because keys of one unlock have different lock versions.
> 3. Cases 1 and 2 with a near cache and k1, k2 on the same primary: a key 
> stays locked silently, because GridNearTransactionalCache#unlockAll sends it 
> under the lock version of another key.
> 4. a.lock(); b.tryLock(timeout) or b.tryLock() fails; a.unlock(): k1 stays 
> locked silently. The rollback of b removes candidates by the version of b and 
> keeps the reentry of k1, which has the version of a.
> 5. On a server node, with k1 primary on this node and first in b, followed by 
> a key with a remote primary: a.lock(); b.lock(); b.unlock(); a.unlock() 
> leaves k1 locked silently, because of the same rollback in 
> GridDhtColocatedLockFuture#mapAsPrimary.
> The attached ExplicitLockReentryUnlockTest reproduces cases 1, 2 and 4.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to