prevent lock values from going negative with memcache backend
This can be caused by the code releasing more locks then it acquires, once the lock value becomes negative it's likely that it will never be able to change into an exclusive lock again. Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
parent
486dff0934
commit
1fa6115779
|
@ -89,14 +89,20 @@ class MemcacheLockingProvider extends AbstractLockingProvider {
|
||||||
*/
|
*/
|
||||||
public function releaseLock($path, $type) {
|
public function releaseLock($path, $type) {
|
||||||
if ($type === self::LOCK_SHARED) {
|
if ($type === self::LOCK_SHARED) {
|
||||||
|
$newValue = 0;
|
||||||
if ($this->getOwnSharedLockCount($path) === 1) {
|
if ($this->getOwnSharedLockCount($path) === 1) {
|
||||||
$removed = $this->memcache->cad($path, 1); // if we're the only one having a shared lock we can remove it in one go
|
$removed = $this->memcache->cad($path, 1); // if we're the only one having a shared lock we can remove it in one go
|
||||||
if (!$removed) { //someone else also has a shared lock, decrease only
|
if (!$removed) { //someone else also has a shared lock, decrease only
|
||||||
$this->memcache->dec($path);
|
$newValue = $this->memcache->dec($path);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if we own more than one lock ourselves just decrease
|
// if we own more than one lock ourselves just decrease
|
||||||
$this->memcache->dec($path);
|
$newValue = $this->memcache->dec($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we somehow release more locks then exists, reset the lock
|
||||||
|
if ($newValue < 0) {
|
||||||
|
$this->memcache->cad($path, $newValue);
|
||||||
}
|
}
|
||||||
} else if ($type === self::LOCK_EXCLUSIVE) {
|
} else if ($type === self::LOCK_EXCLUSIVE) {
|
||||||
$this->memcache->cad($path, 'exclusive');
|
$this->memcache->cad($path, 'exclusive');
|
||||||
|
|
|
@ -243,4 +243,16 @@ abstract class LockingProvider extends TestCase {
|
||||||
$this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
|
$this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
$this->instance->changeLock('foo', ILockingProvider::LOCK_SHARED);
|
$this->instance->changeLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testReleaseNonExistingShared() {
|
||||||
|
$this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
|
$this->instance->releaseLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
|
|
||||||
|
// releasing a lock once to many should not result in a locked state
|
||||||
|
$this->instance->releaseLock('foo', ILockingProvider::LOCK_SHARED);
|
||||||
|
|
||||||
|
$this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
|
||||||
|
$this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
|
||||||
|
$this->instance->releaseLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue