php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #68426 PHP >= 5.6 does not overwrite session file when session has not changed
Submitted: 2014-11-15 20:22 UTC Modified: 2014-11-19 15:30 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: rpkamp at gmail dot com Assigned:
Status: Duplicate Package: Session related
PHP Version: 5.6.3 OS: CentOS 7
Private report: No CVE-ID: None
 [2014-11-15 20:22 UTC] rpkamp at gmail dot com
Description:
------------
I'm running on a system with relatime [1] (which is the default on linux kernels >= 2.6.30 [2]). In short this means that a file's atime doesn't get updated every time that file is accessed, but only if it was also modified.

The thing I found is that unlike earlier versions of PHP, PHP 5.6 does not write the session back to disk again even if nothing has changed (< 5.6 did do this, I tested this using inotifywatch). The problem with this is that when a session is running, and you don't change anything in the session for `session.gc_maxlifetime`, the session will be deleted, regardless of how many times it was accessed. So basically even someone browsing my website for a long time, will get their session terminated after `session.gc_maxlifetime`.
Of course their are workarounds for this, like not using files for sessions but something else, don't mount with relatime, put a timestamp in the session on every page hit forcing the session to be flushed to disk anyway, etc, etc.

My problem with this change however, is that I can't find documentation on it anywhere! The changelog for 5.6 doesn't mention it, the migration manual for 5.5 -> 5.6 doesn't mention it, and there is no info on the session manual as well. I spent about an hour and a half figuring out why my sessions were being terminated for no apparent reason.
I did find that this was done as a result of bug #17860 [3]

I think it's a very useful change and it should stay the way it is (not write to disk if not needed), but it really should be documented so people will know what to expect!

Here is the output of `stat` on my session file, showing exactly what's going on

PHP 5.5
=========================================================================

AFTER FIRST LOAD:

  File: ‘sess_om81e4ohk2r7t8nt7mplc8usm6’
  Size: 14              Blocks: 8          IO Block: 4096   regular file
Device: fd01h/64769d    Inode: 72007296    Links: 1
Access: (0600/-rw-------)  Uid: (   48/  apache)   Gid: (   48/  apache)
Access: 2014-11-15 20:15:28.491063092 +0100
Modify: 2014-11-15 20:15:28.501064363 +0100
Change: 2014-11-15 20:15:28.501064363 +0100
 Birth: -


AFTER REFRESH:

  File: ‘sess_om81e4ohk2r7t8nt7mplc8usm6’
  Size: 14              Blocks: 8          IO Block: 4096   regular file
Device: fd01h/64769d    Inode: 72007296    Links: 1
Access: (0600/-rw-------)  Uid: (   48/  apache)   Gid: (   48/  apache)
Access: 2014-11-15 20:15:57.984811596 +0100  # <-- changed!
Modify: 2014-11-15 20:15:57.984811596 +0100
Change: 2014-11-15 20:15:57.984811596 +0100
 Birth: -


PHP 5.6
=========================================================================

AFTER FIRST LOAD:

  File: ‘sess_om81e4ohk2r7t8nt7mplc8usm6’
  Size: 14              Blocks: 8          IO Block: 4096   regular file
Device: fd01h/64769d    Inode: 69810580    Links: 1
Access: (0600/-rw-------)  Uid: (   48/  apache)   Gid: (   48/  apache)
Access: 2014-11-15 20:51:20.840582376 +0100
Modify: 2014-11-15 20:51:17.658177909 +0100
Change: 2014-11-15 20:51:17.658177909 +0100
 Birth: -


AFTER REFRESH:

  File: ‘sess_om81e4ohk2r7t8nt7mplc8usm6’
  Size: 14              Blocks: 8          IO Block: 4096   regular file
Device: fd01h/64769d    Inode: 69810580    Links: 1
Access: (0600/-rw-------)  Uid: (   48/  apache)   Gid: (   48/  apache)
Access: 2014-11-15 20:51:20.840582376 +0100 # <-- didn't change!
Modify: 2014-11-15 20:51:17.658177909 +0100
Change: 2014-11-15 20:51:17.658177909 +0100
 Birth: -

I'm running this on CentOS 7.0 (Core), my `uname -a` is `Linux pallas 3.10.0-123.9.3.el7.x86_64 #1 SMP Thu Nov 6 15:06:03 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux`, and I'm running NGiNX 1.6.2 with PHP 5.6.3 and PHP-FPM 5.6.3

[1] https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Power_Management_Guide/Relatime.html
[2] http://unix.stackexchange.com/questions/17844/when-was-relatime-made-the-default
[3] https://bugs.php.net/bug.php?id=17860&edit=2

Test script:
---------------
<?php

session_start();

var_dump($_SESSION);

$_SESSION['foo'] = 'bar';

sleep(ini_get('session.gc_maxlifetime') + 10); // +10 to be sure it's really over

Expected result:
----------------
When reloading the page the session should still be there, i.e. the page should show array('foo' => 'bar')

Actual result:
--------------
The session is gone, i.e. the page just shows array()

(depending on `session.gc_probability` and `session.gc_divisor` of course; to replicate this bug one should probably set `session.gc_probability` and `session.gc_divisor` to the same -positive, non-zero- value).

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-11-16 09:00 UTC] mark at grooveshark dot com
So while this is crappy and should be addressed in later PHP versions, I think the issue you're running into will be resolved in the next minor release of PHP 5.6. I brought this up on internals and yohgaki seemed to address it afaik.

See https://bugs.php.net/bug.php?id=68331
 [2014-11-17 20:59 UTC] rpkamp at gmail dot com
It seems to me the solution reached in https://bugs.php.net/bug.php?id=68331 solves this bug as well, so this report can be closed.
 [2014-11-19 15:30 UTC] salathe@php.net
-Status: Open +Status: Duplicate
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Tue Jul 16 00:01:26 2019 UTC