From e08423f95631a1b06f2de0216c5765552092075c Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 19 May 2015 17:12:09 +0200 Subject: [PATCH] release all locks on shutdown --- lib/base.php | 2 ++ lib/private/lock/memcachelockingprovider.php | 27 ++++++++++++++++++++ lib/public/lock/ilockingprovider.php | 5 ++++ 3 files changed, 34 insertions(+) diff --git a/lib/base.php b/lib/base.php index b7f19c9640..09159dc22a 100644 --- a/lib/base.php +++ b/lib/base.php @@ -666,6 +666,8 @@ class OC { //make sure temporary files are cleaned up $tmpManager = \OC::$server->getTempManager(); register_shutdown_function(array($tmpManager, 'clean')); + $lockProvider = \OC::$server->getLockingProvider(); + register_shutdown_function(array($lockProvider, 'releaseAll')); if ($systemConfig->getValue('installed', false) && !self::checkUpgrade(false)) { if (\OC::$server->getConfig()->getAppValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') { diff --git a/lib/private/lock/memcachelockingprovider.php b/lib/private/lock/memcachelockingprovider.php index 9c8c723546..b2938e3a8c 100644 --- a/lib/private/lock/memcachelockingprovider.php +++ b/lib/private/lock/memcachelockingprovider.php @@ -31,6 +31,11 @@ class MemcacheLockingProvider implements ILockingProvider { */ private $memcache; + private $acquiredLocks = [ + 'shared' => [], + 'exclusive' => [] + ]; + /** * @param \OCP\IMemcache $memcache */ @@ -64,11 +69,16 @@ class MemcacheLockingProvider implements ILockingProvider { if (!$this->memcache->inc($path)) { throw new LockedException($path); } + if (!isset($this->acquiredLocks['shared'][$path])) { + $this->acquiredLocks['shared'][$path] = 0; + } + $this->acquiredLocks['shared'][$path]++; } else { $this->memcache->add($path, 0); if (!$this->memcache->cas($path, 0, 'exclusive')) { throw new LockedException($path); } + $this->acquiredLocks['exclusive'][$path] = true; } } @@ -79,8 +89,25 @@ class MemcacheLockingProvider implements ILockingProvider { public function releaseLock($path, $type) { if ($type === self::LOCK_SHARED) { $this->memcache->dec($path); + $this->acquiredLocks['shared'][$path]--; } else if ($type === self::LOCK_EXCLUSIVE) { $this->memcache->cas($path, 'exclusive', 0); + unset($this->acquiredLocks['exclusive'][$path]); + } + } + + /** + * release all lock acquired by this instance + */ + public function releaseAll() { + foreach ($this->acquiredLocks['shared'] as $path => $count) { + for ($i = 0; $i < $count; $i++) { + $this->releaseLock($path, self::LOCK_SHARED); + } + } + + foreach ($this->acquiredLocks['exclusive'] as $path => $hasLock) { + $this->releaseLock($path, self::LOCK_EXCLUSIVE); } } } diff --git a/lib/public/lock/ilockingprovider.php b/lib/public/lock/ilockingprovider.php index 0b17580faa..18fa47fa63 100644 --- a/lib/public/lock/ilockingprovider.php +++ b/lib/public/lock/ilockingprovider.php @@ -44,4 +44,9 @@ interface ILockingProvider { * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE */ public function releaseLock($path, $type); + + /** + * release all lock acquired by this instance + */ + public function releaseAll(); }