Commit 6ec361c6 authored by Petr Škoda's avatar Petr Škoda
Browse files

MDL-42485 add session lock acquire timeout to memcached session driver

Credit goes to Eric Merrill, thanks!
parent 68291f2d
......@@ -237,6 +237,8 @@ $CFG->admin = 'admin';
// $CFG->session_handler_class = '\core\session\memcached';
// $CFG->session_memcached_save_path = '127.0.0.1:11211';
// $CFG->session_memcached_prefix = 'memc.sess.key.';
// $CFG->session_memcached_acquire_lock_timeout = 120;
// $CFG->session_memcached_lock_expire = 7200; // Ignored if memcached extension <= 2.1.0
//
// Following setting allows you to alter how frequently is timemodified updated in sessions table.
// $CFG->session_update_timemodified_frequency = 20; // In seconds.
......
......@@ -34,6 +34,14 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class handler {
/**
* Start the session.
* @return bool success
*/
public function start() {
return session_start();
}
/**
* Init session handler.
*/
......
......@@ -74,7 +74,7 @@ class manager {
self::prepare_cookies();
$newsid = empty($_COOKIE[session_name()]);
session_start();
self::$handler->start();
self::initialise_user_session($newsid);
self::check_security();
......
......@@ -40,6 +40,13 @@ class memcached extends handler {
protected $servers;
/** @var string $prefix session key prefix */
protected $prefix;
/** @var int $acquiretimeout how long to wait for session lock */
protected $acquiretimeout = 120;
/**
* @var int $lockexpire how long to wait before expiring the lock so that other requests
* may continue execution, ignored if memcached <= 2.1.0.
*/
protected $lockexpire = 7200;
/**
* Create new instance of handler.
......@@ -64,6 +71,32 @@ class memcached extends handler {
} else {
$this->prefix = $CFG->session_memcached_prefix;
}
if (!empty($CFG->session_memcached_acquire_lock_timeout)) {
$this->acquiretimeout = (int)$CFG->session_memcached_acquire_lock_timeout;
}
if (!empty($CFG->session_memcached_lock_expire)) {
$this->lockexpire = (int)$CFG->session_memcached_lock_expire;
}
}
/**
* Start the session.
* @return bool success
*/
public function start() {
// NOTE: memcached <= 2.1.0 expires session locks automatically after max_execution_time,
// this leads to major difference compared to other session drivers that timeout
// and stop the second request execution instead.
$default = ini_get('max_execution_time');
set_time_limit($this->acquiretimeout);
$result = parent::start();
set_time_limit($default);
return $result;
}
/**
......@@ -81,11 +114,14 @@ class memcached extends handler {
throw new exception('sessionhandlerproblem', 'error', '', null, '$CFG->session_memcached_save_path must be specified in config.php');
}
// NOTE: we cannot set any lock acquiring timeout here - bad luck.
ini_set('session.save_handler', 'memcached');
ini_set('session.save_path', $this->savepath);
ini_set('memcached.sess_prefix', $this->prefix);
ini_set('memcached.sess_locking', '1'); // Locking is required!
// Try to configure lock and expire timeouts - ignored if memcached <=2.1.0.
ini_set('memcached.sess_lock_max_wait', $this->acquiretimeout);
ini_set('memcached.sess_lock_expire', $this->lockexpire);
}
/**
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment