Fix #3627: Keep timed locks for more than 5 seconds

Emulated locks for Redis and Memcached now have a TTL
of 300 seconds (the default HTTP request timeout value
on many environments) and 30 attemps, each separated by
sleep(1), are made by the blocked request to try and
obtain a lock if it has been freed.

Additionaly, the blocking time for MySQL's locks,
which are also timed, is also set to 300 seconds.
diff --git a/system/libraries/Session/drivers/Session_memcached_driver.php b/system/libraries/Session/drivers/Session_memcached_driver.php
index f1a6e24..938a612 100644
--- a/system/libraries/Session/drivers/Session_memcached_driver.php
+++ b/system/libraries/Session/drivers/Session_memcached_driver.php
@@ -204,7 +204,7 @@
 
 		if (isset($this->_lock_key))
 		{
-			$this->_memcached->replace($this->_lock_key, time(), 5);
+			$this->_memcached->replace($this->_lock_key, time(), 300);
 			if ($this->_fingerprint !== ($fingerprint = md5($session_data)))
 			{
 				if ($this->_memcached->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration']))
@@ -299,34 +299,21 @@
 	{
 		if (isset($this->_lock_key))
 		{
-			return $this->_memcached->replace($this->_lock_key, time(), 5);
+			return $this->_memcached->replace($this->_lock_key, time(), 300);
 		}
 
+		// 30 attempts to obtain a lock, in case another request already has it
 		$lock_key = $this->_key_prefix.$session_id.':lock';
-		if ( ! ($ts = $this->_memcached->get($lock_key)))
-		{
-			if ( ! $this->_memcached->set($lock_key, TRUE, 5))
-			{
-				log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);
-				return FALSE;
-			}
-
-			$this->_lock_key = $lock_key;
-			$this->_lock = TRUE;
-			return TRUE;
-		}
-
-		// Another process has the lock, we'll try to wait for it to free itself ...
 		$attempt = 0;
-		while ($attempt++ < 5)
+		do
 		{
-			usleep(((time() - $ts) * 1000000) - 20000);
-			if (($ts = $this->_memcached->get($lock_key)) < time())
+			if ($this->_memcached->get($lock_key))
 			{
+				sleep(1);
 				continue;
 			}
 
-			if ( ! $this->_memcached->set($lock_key, time(), 5))
+			if ( ! $this->_memcached->set($lock_key, time(), 300))
 			{
 				log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);
 				return FALSE;
@@ -335,8 +322,9 @@
 			$this->_lock_key = $lock_key;
 			break;
 		}
+		while ($attempt++ < 30);
 
-		if ($attempt === 5)
+		if ($attempt === 30)
 		{
 			log_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 5 attempts, aborting.');
 			return FALSE;