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

Pull Requests

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