Press "Enter" to skip to content

PHP Internals — A Low-Probability Notice in Session GC

If you installed PHP via apt on ubuntu/Debian, then when using Sessions you may occasionally run into this notice:

PHP Notice: session_start(): ps_files_cleanup_dir:
   opendir(/var/lib/php5) failed: Permission denied (13)
   in /home/laruence/www/htdocs/index.php on line 22

This is because in PHP, when using file_handler as the Session save handler, there's a probability that the Session GC process runs on each session_start:

//abridged
        int nrdels = -1;
        nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg(TSRMLS_C));
        if (nrand < PS(gc_probability)) {
            PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels TSRMLS_CC);
        }
//abridged

The reason for this warning is that in the apt PHP, the default session directory /var/lib/php5 has permissions of 733 with the sticky bit, i.e.

drwx-wx-wt  root  root

And PHP workers generally run as a non-root user, so they have no permission to open this directory (though because they can write, normal Session file access isn't affected). So the following code in s_gc triggers the Notice described above:

//for the file handler, s_gc indirectly calls ps_files_cleanup_dir:
   dir = opendir(dirname);
    if (!dir) {
        php_error_docref(NULL TSRMLS_CC, E_NOTICE,
           "ps_files_cleanup_dir: opendir(%s) failed: %s (%d)",
           dirname, strerror(errno), errno);
        return (0);
    }

Of course, on ubuntu/Debian there's still GC cleanup — it's just done by an external cron process. By default it's in /etc/cron.d/php5:

09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ]
&& [ -d /var/lib/php5 ] && find /var/lib/php5/
 -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0
| xargs -n 200 -r -0 rm

Also, you can see that when deciding whether s_gc runs, there are two key variables: PS(gc_divisor) and PS(gc_probability). These correspond to two same-named session runtime settings:
session.gc_probability and session.gc_divisor, defaulting to 1 and 100 respectively.
And php_combined_lcg is a random number generator producing a value in the 0–1 range, so the check above is equivalent to:

 rand < probability / gc_divisor

That is, by default the GC process is triggered roughly once every 100 times. That's why you only see this Notice with a small probability.
To silence this Notice, simply set:
session.gc_probability = 0, so s_gc has no chance to run at all.
Of course, you can also change the permissions on that folder...
Finally, thanks to CFC4N for reporting this issue.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.