Session issues with frontend login

We’ve build a members site that is only accessible to Kirby users after login. We provide a login form on the frontend as well as a logout link. From time to time – either after login or logout – Kirby throws this error: Cannot write to session xyz, because it is not locked. A logic exception that is triggered in kirby/FileSessionStore.php at master · getkirby/kirby · GitHub.

Can anyone explain why this is happening and what we can do about it?

It seems that after deleting the session on the server and waiting for a few minutes, the error goes away silently. But it would be nice to prevent the error in the first place or – if that’s not possible – to fix it for the user without blocking the login.

This is our (simplified) login code:

// this is from an Uniform action file
$email = $this->form->data('email');
$password = $this->form->data('password');
$remember = $this->form->data('remember');

if($user = $kirby->users()->findByKey($email)) {
	$session = null;
	if ($remember) {
		$session = $kirby->session(['long' => true]);
	}

	$user->login($password, $session);
}

The logout can be triggered by appending ?logout to any URL:

// config.php
return [
	'routes' = [
		[
			'pattern' => '(:all)',
			'method' => 'GET',
			'action' => function ($all) {
				$user = kirby()->user();
	
				if ($user && get('logout') !== null) {
					$user->logout();
					$user = null;
				}
	
				if (!$user) {
					go('/login');
				}
	
				$this->next();
			}
		]
	]
];

When this happens on logout the following backtrace is shown after $user->logout() is called:

Kirby\Exception\LogicException 
    .../src/Session/FileSessionStore.php:263
Kirby\Session\FileSessionStore set 
    .../src/Session/Session.php:373
Kirby\Session\Session commit 
    .../src/Session/Session.php:446
Kirby\Session\Session regenerateToken 
    .../src/Cms/User.php:469

I’m not sure what regenerateToken actually does after logout.

I‘m pretty sure it‘s a file system error.

Does it only happen on the production server or have you run into it in development as well?

I’ve seen it happening locally and on the production server. It actually happend on production first and it’s not reduced to our frontend case but might also happen when trying to log into the panel.

I’m using MAMP with PHP 8.0.3 locally under macOS Big Sur.
The production server also runs PHP 8.

If it actually is a filesystem error, are there any steps we can apply when catching the error to solve this issue automatically for the user? Something like dismissing all user related sessions stuff and starting over again?

Which operating system are you using on the production server? And for both, which file systems and which kind of storage medium (SSD or HDD)?

I’ve seen this issue at a hosting provider with a quite flaky HDD-based storage cluster before, but never on reliable servers so far. We had another report on GitHub and before that 2-3 other users ran into it, but so far it looks like no one ran into it repeatedly. So maybe there’s something specific to your setup that triggers it more often. Hopefully we can debug this together.

A bit of background information:

Our default file session storage uses advisory locking, a file system feature that allows to tell other threads or processes that a specific session file is currently in use. There are two kinds of locks: shared (= read) locks and exclusive (= write) locks. Kirby only writes to a session file if it was able to obtain an exclusive lock before. This prevents other requests from interfering with the write operation (which could be abused by an attacker and therefore has a high security relevance). So I don’t recommend circumventing this error.

What’s really weird is that the error is thrown based on the internal FileSessionStore::$isLocked array. This gets set by the lock() method, which is always called before writing anything to the session file. So Kirby’s internal state seems to be mismatched, but why? I’m really confused as well.

I will be able to give you more information tomorrow, but a few notes:

  • We’re using a HDD locally, I‘m not sure about the production server. It‘s a shared host at all-inkl.com which has been reliable so far.
  • All errors have been encountered in Firefox. We‘ve not seen this issue in other browsers so far.
  • The maximum count of users of the entire site is 50, in case there might be some interference.

That could have been by chance though. How long has the site been running and how often did the issue occur so far? Are other browsers used in the same intensity as Firefox?

I don’t think so.