Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKate Butler <kate@innocraft.com>2019-12-23 00:21:28 +0300
committerThomas Steur <tsteur@users.noreply.github.com>2019-12-23 00:21:28 +0300
commit954f6ce2936818e35cc80083526e9ffbe6ea58c6 (patch)
treeb49bf1708fd3d307ef86bd346ecb7eb0366181f6 /core/Concurrency
parenta9a94e937b5faec70e5388c527517ac8dd531fa2 (diff)
Prevent race conditions when updating plugin settings (#15249)
Diffstat (limited to 'core/Concurrency')
-rw-r--r--core/Concurrency/Lock.php26
1 files changed, 26 insertions, 0 deletions
diff --git a/core/Concurrency/Lock.php b/core/Concurrency/Lock.php
index 7a7de32a37..e3200310bd 100644
--- a/core/Concurrency/Lock.php
+++ b/core/Concurrency/Lock.php
@@ -12,6 +12,8 @@ use Piwik\Common;
class Lock
{
+ const MAX_KEY_LEN = 70;
+
/**
* @var LockBackend
*/
@@ -39,6 +41,30 @@ class Lock
return $this->backend->getKeysMatchingPattern($this->lockKeyStart . '*');
}
+ public function execute($id, $callback)
+ {
+ if (Common::mb_strlen($id) > self::MAX_KEY_LEN) {
+ // Lock key might be too long for DB column, so we hash it but leave the start of the original as well
+ // to make it more readable
+ $md5Len = 32;
+ $id = Common::mb_substr($id, 0, self::MAX_KEY_LEN - $md5Len - 1) . md5($id);
+ }
+
+ $i = 0;
+ while (!$this->acquireLock($id)) {
+ $i++;
+ usleep( 100 * 1000 ); // 100ms
+ if ($i > 50) { // give up after 5seconds (50 * 100ms)
+ throw new \Exception('Could not get the lock for ID: ' . $id);
+ }
+ };
+ try {
+ return $callback();
+ } finally {
+ $this->unlock();
+ }
+ }
+
public function acquireLock($id, $ttlInSeconds = 60)
{
$this->lockKey = $this->lockKeyStart . $id;