-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BugFix] It is strictly forbidden to use read-write locks inside Intend Lock #48530
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,7 +46,7 @@ public MultiUserLock(LockHolder lockHolder) { | |
} | ||
|
||
@Override | ||
public LockGrantType lock(Locker locker, LockType lockType) { | ||
public LockGrantType lock(Locker locker, LockType lockType) throws LockException { | ||
LockHolder lockHolderRequest = new LockHolder(locker, lockType); | ||
LockGrantType lockGrantType = tryLock(lockHolderRequest); | ||
if (lockGrantType == LockGrantType.NEW) { | ||
|
@@ -58,7 +58,7 @@ public LockGrantType lock(Locker locker, LockType lockType) { | |
return lockGrantType; | ||
} | ||
|
||
private LockGrantType tryLock(LockHolder lockHolderRequest) { | ||
private LockGrantType tryLock(LockHolder lockHolderRequest) throws LockException { | ||
if (ownerNum() == 0) { | ||
return LockGrantType.NEW; | ||
} | ||
|
@@ -91,10 +91,24 @@ private LockGrantType tryLock(LockHolder lockHolderRequest) { | |
lockOwner.getLocker(), lockOwner.getLockType(), lockHolderRequest.getLockType(), this); | ||
} | ||
|
||
if (lockHolderRequest.getLockType().equals(lockOwner.getLockType())) { | ||
LockType lockOwnerLockType = lockOwner.getLockType(); | ||
LockType lockRequestLockType = lockHolderRequest.getLockType(); | ||
|
||
if (lockRequestLockType.equals(lockOwnerLockType)) { | ||
lockOwner.increaseRefCount(); | ||
return LockGrantType.EXISTING; | ||
} else { | ||
/* | ||
* This does not conform to the use of hierarchical locks. | ||
* The outer layer has already obtained the intention lock, | ||
* and the inner layer code should not apply for read-write locks. | ||
*/ | ||
if ((lockOwnerLockType == LockType.INTENTION_SHARED || lockOwnerLockType == LockType.INTENTION_EXCLUSIVE) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should mark the lock table with intention or not |
||
&& (lockRequestLockType == LockType.READ || lockRequestLockType == LockType.WRITE)) { | ||
throw new NotSupportLockException("Can't request " + lockRequestLockType | ||
+ " in the scope of " + lockOwnerLockType + ", " + lockOwner.getLocker().getLockerStackTrace()); | ||
} | ||
|
||
/* | ||
* The same Locker can upgrade or degrade locks when it requests different types of locks | ||
* | ||
|
@@ -128,7 +142,7 @@ private LockGrantType tryLock(LockHolder lockHolderRequest) { | |
} | ||
|
||
@Override | ||
public Set<Locker> release(Locker locker, LockType lockType) { | ||
public Set<Locker> release(Locker locker, LockType lockType) throws LockException { | ||
boolean hasOwner = false; | ||
boolean reentrantLock = false; | ||
LockHolder lockHolder = new LockHolder(locker, lockType); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The most risky bug in this code is: You can modify the code like this: public MultiUserLock(LockHolder lockHolder) { }
@Override
public LockGrantType lock(Locker locker, LockType lockType) throws LockException {
LockHolder lockHolderRequest = new LockHolder(locker, lockType);
LockGrantType lockGrantType = tryLock(lockHolderRequest);
if (lockGrantType == LockGrantType.NEW) {
addHolder(locker, lockType);
}
return lockGrantType;
}
private LockGrantType tryLock(LockHolder lockHolderRequest) throws LockException, NotSupportLockException {
if (ownerNum() == 0) {
return LockGrantType.NEW;
}
for (LockHolder lockOwner : currentOwners()) {
if (!lockOwner.getLocker().equals(lockHolderRequest.getLocker())) {
checkCompatibility(lockOwner.getLocker(), lockOwner.getLockType(), lockHolderRequest.getLockType(), this);
}
LockType lockOwnerLockType = lockOwner.getLockType();
LockType lockRequestLockType = lockHolderRequest.getLockType();
if (lockRequestLockType.equals(lockOwnerLockType)) {
lockOwner.increaseRefCount();
return LockGrantType.EXISTING;
} else {
if ((lockOwnerLockType == LockType.INTENTION_SHARED || lockOwnerLockType == LockType.INTENTION_EXCLUSIVE)
&& (lockRequestLockType == LockType.READ || lockRequestLockType == LockType.WRITE)) {
throw new NotSupportLockException("Can't request " + lockRequestLockType
+ " in the scope of " + lockOwnerLockType + ", " + lockOwner);
}
// Handle upgrading or downgrading locks here
}
}
return LockGrantType.WAIT;
}
@Override
public Set<Locker> release(Locker locker, LockType lockType) throws LockException {
boolean hasOwner = false;
boolean reentrantLock = false;
LockHolder lockHolder = new LockHolder(locker, lockType);
// Implementation of release logic
return new HashSet<>();
} |
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The most risky bug in this code is:
Catching
LockException
in therelease
method might suppress important exceptions and not handle them properly.You can modify the code like this: