Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP 7 user sessions issue - Failed to initialize storage module

A bug exists when using various PHP framework session drivers with PHP 7.0. I initially experienced this issue while using the CodeIgniter database driver and assumed it was a CodeIgniter issue but have since experienced it on multiple sessions drivers and multiple frameworks. At this point I have safely concluded that the type of session driver is irrelevant - seemingly at random, the application will crash and the logs (I've tried both Apache and php-fpm + nginx) fill up with the following:

PHP Fatal error: session_start(): Failed to initialize storage module: user (path: [whatever I have in my php.ini path])

The drivers I am using do not use the values set in php.ini and regardless of whether I set the session.save_handler to files, redis, etc in php.ini and regardless of the path I set (Redis server if redis, fully-writable folder with files enabled) the errors occur. The path here should never be hit unless a native "session_start()" is called in a php file outside of the framework. Also, calling "session_start()" outside of the framework works fine... so clearly PHP can access the path. It's as if at some point, the sessions driver becomes a hybrid of the framework driver and whatever is set in php.ini. The error message always has "user" for the session.save_handler so obviously that's not being pulled from php.ini... but the path is. Why would this be happening? This is one of those issues that is difficult to describe until you have experienced it... and it's difficult to reproduce because everything seems to work fine even for hundreds of sessions (until it suddenly stops working). Restarting Apache does not correct the issue either - there are a number of issues at play here and I end up just rebooting the machine to avoid the downtime. Obviously the PHP 7 machine will be pulled out of the load balancer rotation now... but I was hoping to have things figured out by now.

I have experienced the issue with PHP 7.0 RC5, RC6, & RC8 compiled on my own as well as the latest Ondřej Surý PPA on Ubuntu 15.10 Wily (7.0.0-2+deb.sury.org~wily+1). I have experienced the issue on CodeIgniter & Symfony, and have experienced the issue regardless of the type of driver used in the framework (files, database, redis) or the session.save_handler set in php.ini (which, again, should be irrelevant here but just thought it should be mentioned). I keep trying combinations and throwing things out in the wild and this issue happens every single time (sometimes it takes 12+ hours depending on the traffic to the website).

Thanks for any help you can provide! I'm open to suggestions and willing to try anything at this point.

like image 546
DrBlueSpruce Avatar asked Dec 07 '15 03:12

DrBlueSpruce


4 Answers

This error occurs when the open() function of the session handler doesn't return boolean TRUE, which obviously means some kind of failure.

It could be failure to connect to a database, failure to open a file, a non-existent directory, etc. - that depends on what the session handler actually uses.

like image 96
Narf Avatar answered Oct 19 '22 07:10

Narf


function _open should return true to avoid this error.

It can not be null or empty whatever we use either database or file.

When we use database to store session data, we keep it blank or no Boolean return. that is the main reason for this error.

class session_handler
{
    public function __construct()
    {
        session_set_save_handler(
            array($this, "_open"),
            array($this, "_close"),
            array($this, "_read"),
            array($this, "_write"),
            array($this, "_destroy"),
            array($this, "_gc")
        );
    }

    public function _open($savePath, $sessionId)
    {
        return true;
    }

    public function _close() {  }    
    public function _read($id) {  }
    public function _write($id, $data) {  }
    public function _destroy($id) {  }
    public function _gc($max) {  }
}

It is only for PHP 7. I do not know it is a bug or not.

like image 42
Moin Uddin Avatar answered Oct 19 '22 06:10

Moin Uddin


This is usually is due to the session not being able to connect to whichever driver it uses (file, database).

I resolved the issue by looking at the config.php file

    $config['sess_driver'] = 'database';
    $config['sess_cookie_name'] = 'ci_session';
    $config['sess_expiration'] = 7200;
    $config['sess_save_path'] = 'ci_sessions';
    $config['sess_match_ip'] = FALSE;
    $config['sess_time_to_update'] = 300;
    $config['sess_regenerate_destroy'] = FALSE;

So since I used a database it means that it doesn't connect for some reason! (For files probably it doesn't have the permission to write the cached files )

Next I turned on the log

    $config['log_threshold'] = 4;

Where 4 = All Messages.. Then refresh the page, and now I have in application/logs a file called log-#.php where # is a date.

    INFO - 2017-08-30 10:05:41 --> Database Driver Class Initialized
    ERROR - 2017-08-30 10:05:41 --> Severity: Warning --> mysqli::real_connect(): (HY000/1045): Access denied for user 'user'@'localhost' (using password: YES) /var/system/database/drivers/mysqli/mysqli_driver.php 202
    ERROR - 2017-08-30 10:05:41 --> Unable to connect to the database
    ERROR - 2017-08-30 10:05:41 --> Severity: Warning --> mysqli::real_connect(): (HY000/1045): Access denied for user 'user'@'localhost' (using password: YES) var/system/database/drivers/mysqli/mysqli_driver.php 202
    ERROR - 2017-08-30 10:05:41 --> Severity: Error --> session_start(): Failed to initialize storage module: user (path: ci_sessions) /var/system/libraries/Session/Session.php 140

So I just make sure that the user can access the database and it worked.

like image 3
Saln3t Avatar answered Oct 19 '22 07:10

Saln3t


I decided to migrate my system and do some much-needed updating. I ran into this issue using Codeigniter 3 and php 7.2. After I found the issue I realized how ridiculous it was and wonder how I didn't figure it out sooner. 😏

Anyway here is the solution at least for me.

Obviously make sure memcacheD is installed:

sudo apt-get update
sudo apt-get install php7.2-memcached

If that is good to go then we can proceed to check everything else.

In Codeigniter's config file "/application/config/config.php" there is a section to to specify session options:

$config['sess_driver'] = 'memcached';
$config['sess_cookie_name'] = 'some_session_name';
$config['sess_expiration'] = 7200;
$config['sess_save_path'] = NULL;
$config['sess_match_ip'] = FALSE;
$config['sess_time_to_update'] = 300;
$config['sess_regenerate_destroy'] = FALSE;

The line that needed to be changed for me was this line:

$config['sess_save_path'] = NULL;

Make sure you set this to a valid path as documented in CI3's manual. The correct setting will look like this:

$config['sess_driver'] = 'memcached';
$config['sess_save_path'] = 'localhost:11211';

Make sure you change "localhost" to reflect your memcached servers location.

For more info see - Codeignier Session Manual

Also have a look here: php memcacheD Sessions support

In case the comment on the page is removed I am posting here:

If you want to use 'memcacheD' extention not 'memcache' (there are two diffrent extentions) for session control, you should pay attention to modify php.ini

Most web resource from google is based on memcache because It's earlier version than memcacheD. They will say as following

session.save_handler = memcache session.save_path = "tcp://localhost:11211"

But it's not valid when it comes to memcacheD

you should modify php.ini like that

session.save_handler = memcached session.save_path = "localhost:11211"

Look, there is no protocol indentifier

For testing I did this to make user that php it's self wasn't having an issue accessing memcacheD:

session_start();

    header('Content-Type: text/plain');
    session_start();
    if(!isset($_SESSION['visit']))
    {
        echo "This is the first time you're visiting this server\n";
        $_SESSION['visit'] = 0;
    }
    else
            echo "Your number of visits: ".$_SESSION['visit'] . "\n";

    $_SESSION['visit']++;

    echo "Server IP: ".$_SERVER['SERVER_ADDR'] . "\n";
    echo "Client IP: ".$_SERVER['REMOTE_ADDR'] . "\n";
    print_r($_COOKIE);

$servers = explode(",", ini_get("session.save_path"));
$c = count($servers);
for ($i = 0; $i < $c; ++$i) {
  $servers[$i] = explode(":", $servers[$i]);
}


$mem = new memcached();

$mem->addServer('127.0.0.1', '11211', '1');
$mem->set('011', 'Hello There');

print_r($mem->get('011'));

print_r($mem->getAllKeys());

This allowed me to see that memcacheD was working ok.

Also in your php.ini there are some options to look out for. Just search for [session] or session.save_path. CI3 stated it doesn't use this option from the php.ini file, but it's prob worth setting if you plan to use memcacheD outside the framework and for consistency.

This starts around line ~1327 in the php.ini file:

[Session]
; Handler used to store/retrieve data.
; http://php.net/session.save-handler
session.save_handler = memcached

; Argument passed to save_handler.  In the case of files, this is the path
; where data files are stored. Note: Windows users have to change this
; variable in order to use PHP's session functions.
;
; The path can be defined as:
;
;     session.save_path = "N;/path"
;
; where N is an integer.  Instead of storing all the session files in
; /path, what this will do is use subdirectories N-levels deep, and
; store the session data in those directories.  This is useful if
; your OS has problems with many files in one directory and is
; a more efficient layout for servers that handle many sessions.
;
; NOTE 1: PHP will not create this directory structure automatically.
;         You can use the script in the ext/session dir for that purpose.
; NOTE 2: See the section on garbage collection below if you choose to
;         use subdirectories for session storage
;
; The file storage module creates files using mode 600 by default.
; You can change that by using
;
;     session.save_path = "N;MODE;/path"
;
; where MODE is the octal representation of the mode. Note that this
; does not overwrite the process's umask.
; http://php.net/session.save-path
;session.save_path = "/var/lib/php/sessions"
session.save_path = "locahost:11211"

One other place to check settings is the mecacheD server config file. Depending on the system it's location may vary. For me, it was located under the /etc/ directory.

/etc/memcached.conf

Image for reference to the errors I was getting:

Image of Errors

EDIT

If you are using socket i.e. unix:///some/place/memcached.sock to connect to Memcached server it's not documented on exactly how to make this work. You simply do the following in your config:

$config['sess_save_path'] = "/some/place/memcached.sock:11211";
like image 2
Kyle Coots Avatar answered Oct 19 '22 07:10

Kyle Coots