Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
kenjis opened this issue Feb 21, 2024 · 0 comments · Fixed by #8323
Closed

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

kenjis opened this issue Feb 21, 2024 · 0 comments · Fixed by #8323
Labels
bug Verified issues on the current code behavior or pull requests that will fix them

Comments

@kenjis
Copy link
Member

kenjis commented Feb 21, 2024

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 →
@kenjis kenjis added the bug Verified issues on the current code behavior or pull requests that will fix them label Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Verified issues on the current code behavior or pull requests that will fix them
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant