Skip to content

Bug: Redis Session data is lost if lock error happens #8567

@kenjis

Description

@kenjis

CodeIgniter4 Version: develop after 4.4.5

From

What happened?

If the lockSession() fails when reading the data from Redis, it returns ''.
And it clears the session data, and the data will be saved when closing the session.

public function read($id)
{
if (isset($this->redis) && $this->lockSession($id)) {
if (! isset($this->sessionID)) {
$this->sessionID = $id;
}
$data = $this->redis->get($this->keyPrefix . $id);
if (is_string($data)) {
$this->keyExists = true;
} else {
$data = '';
}
$this->fingerprint = md5($data);
return $data;
}
return '';
}

if ($attempt === 30) {
log_message('error', 'Session: Unable to obtain lock for ' . $this->keyPrefix . $sessionID . ' after 30 attempts, aborting.');
return false;
}

    public function index()
    {
        $session = session();
        var_dump($_SESSION);

        $count = $session->get('count') ?? 0;
        $count++;
        $session->set('count', $count);

        var_dump($_SESSION);
    }

Navigate to http://localhost:8080/ and reload many times.

/Users/kenji/work/codeigniter/official/CodeIgniter4/app/Controllers/Home.php:11:
array (size=3)
  '__ci_last_regenerate' => int 1708569979
  'count' => int 4024
  '_ci_previous_url' => string 'http://localhost:8080/index.php/' (length=32)

/Users/kenji/work/codeigniter/official/CodeIgniter4/app/Controllers/Home.php:17:
array (size=3)
  '__ci_last_regenerate' => int 1708569979
  'count' => int 4025
  '_ci_previous_url' => string 'http://localhost:8080/index.php/' (length=32)

Modify the code for testing.

--- a/system/Session/Handlers/RedisHandler.php
+++ b/system/Session/Handlers/RedisHandler.php
@@ -150,6 +150,8 @@ class RedisHandler extends BaseHandler
     #[ReturnTypeWillChange]
     public function read($id)
     {
+        return '';
+
         if (isset($this->redis) && $this->lockSession($id)) {
             if (! isset($this->sessionID)) {
                 $this->sessionID = $id;

Navigate to http://localhost:8080/ again.

Result:

/Users/kenji/work/codeigniter/official/CodeIgniter4/app/Controllers/Home.php:11:
array (size=1)
  '__ci_last_regenerate' => int 1708570128

/Users/kenji/work/codeigniter/official/CodeIgniter4/app/Controllers/Home.php:17:
array (size=2)
  '__ci_last_regenerate' => int 1708570128
  'count' => int 1

Expected Output

If read() returns false, the following error occurs.
But the session data remains.

ErrorException
session_start(): Failed to read session data: user (path: tcp://localhost:6379) search →

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugVerified issues on the current code behavior or pull requests that will fix them

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions