1

There are cases when session_start(); returns true even if it can't actually start the session. One can see that from the error log:

PHP Warning:  session_start(): 
     open(/var/lib/php5/sessions/sess_XXXXXXX, O_RDWR) failed: 
     Permission denied (13)

I've seen this happen if a programmer thinks he can use the same session ID on different websites, but they actually use different privileges and can't access each other files. And I can't say this programmer, like, hey, check what session_start() returns and act accordingly because he'd tell me he checks and it reports all good.

One can simulate this problem by removing write privileges from a specific session file:

chmod a-w /var/lib/php5/sessions/sess_XXXXXXX

And then staring a session with the same ID:

session_start(); // returns true with a warning in the logs
// if it'd return false, there would be no question
// PHP thinks session is started: session_status() == PHP_SESSION_ACTIVE

What is the proper way to deal with such errors in software? E.g. how do I know that I have this kind of error but not by looking in the logs?

So far I've come to this:

set_error_handler(function ($errno, $errstr) {
    // we got an error during session_start()
    if (strpos($errstr, 'session_start') === 0) {
        // forget previus session ID
        session_regenerate_id();
        // restore the handler for now
        set_error_handler(null);
    }
    return false;
}, E_WARNING);

if (!session_start()) {
    // et cetera
}

// session shall be running now
// restore the error handler
set_error_handler(null);

(My inspiration comes from phpMyAdmin, which also does something similar.)

sanmai
  • 29,083
  • 12
  • 64
  • 76
  • I don't understand why you're using negation for `session_start()`. Are you trying to check if the session is started or not? or, is that deliberate? – Funk Forty Niner Apr 27 '15 at 03:21
  • @Fred-ii- If a session fails to start for other than explained reasons, [then FALSE is returned](http://php.net/manual/en/function.session-start.php) – sanmai Apr 27 '15 at 03:24
  • *"how do I know that I have this kind of error but not by looking in the logs?"* - if I am understanding this, add `error_reporting(E_ALL); ini_set("display_errors", 1);` at the start of your files. this will only display it on screen; that's **if** I am grasping this correctly. http://php.net/manual/en/function.error-reporting.php – Funk Forty Niner Apr 27 '15 at 03:32
  • @Fred-ii- you, as a developer, still wouldn't know it – sanmai Apr 27 '15 at 03:34
  • I guess I don't understand the question then, sorry. however, what do you mean by that exactly? or was that a question? *still wouldn't know it* - sounds like you're telling me that I don't. – Funk Forty Niner Apr 27 '15 at 03:35
  • @Fred-ii- how do you know your sessions aren't working if `session_start()` return true? – sanmai Apr 27 '15 at 03:41
  • *how do I know that sessions aren't working right if I'm not the one who adds an item to the cart?* - your question's a bit unclear. but it sounds to me like you need to check if the session is set by using `isset()`. I.e.: `if(isset($_SESSION['var'])){...}` or `!empty()` that's what I get out all this. – Funk Forty Niner Apr 27 '15 at 03:42
  • @Fred-ii- how do I check that if the session *just* started? Remember, session starts empty. Please add your answer. – sanmai Apr 27 '15 at 03:43
  • see this Q&A http://stackoverflow.com/q/6249707/ and http://php.net/manual/en/function.session-status.php your answers are in there. – Funk Forty Niner Apr 27 '15 at 03:47
  • @Fred-ii- `session_status()` return `PHP_SESSION_ACTIVE` even if there is this error – sanmai Apr 27 '15 at 03:54

2 Answers2

0

You shouldn't try to resolve this with software, you should correct the server configuration. In this case, ensure the user the server is running as - either apache or www-data or nobody, has write permissions for the PHP session storage directory and files.

You can find out which user PHP is running under by using:

<?php echo `whoami`; ?>
user2182349
  • 9,569
  • 3
  • 29
  • 41
  • I've updated the question. It's okay to fix the server configuration, but how would you know that you need to do just that? `session_start();` gives you no error whatsoever, and you can't check with the logs every time you store someone's shopping cart. – sanmai Apr 27 '15 at 03:31
  • You will know you need to check the configuration when the sessions aren't working right, for example you add an item to the cart but your cart remains empty. You should check the error logs. When you are working on the project, set 'display_errors' on to show the errors. Be sure to shut it off before you go to production. – user2182349 Apr 27 '15 at 03:34
  • how do I know that sessions aren't working right if I'm not the one who adds an item to the cart? – sanmai Apr 27 '15 at 03:35
  • Try logging in to the admin console. – user2182349 Apr 27 '15 at 03:38
  • if i'd do that, there's no problem and no error because I have *different session ID* which is stored in a different file which the server can access – sanmai Apr 27 '15 at 03:40
  • Clear all your cookies, then try to log in to the admin console. If it works, you're all set. If it doesn't, you should consider updating the server configuration. – user2182349 Apr 27 '15 at 03:46
  • I have no problems with session, but someone I don't know very far away can't add things into his cart. How do I know that this is happening? – sanmai Apr 27 '15 at 04:00
0

Catching errors and warning are fun, but you never know if you got them right. What you really need is to check that you can actually save something to the session.

function verify_session_writable()
{
    // if session has been started yet there's no canary
    if (empty($_SESSION[__FUNCTION__]) && 
                session_status() == PHP_SESSION_ACTIVE) {
        // set the canary
        $_SESSION[__FUNCTION__] = 1;
        // write the session to a file
        session_write_close();
        // and load it once again
        session_start();

        // if there's no canary, it's an error
        if (empty($_SESSION[__FUNCTION__])) {
            // change session ID to make sure the write
            // happens to a file with a different name
            session_regenerate_id();
            // set the canary to skip futher checks
            $_SESSION[__FUNCTION__] = 1;
        }
    }
}

I call this function in every place I need to be sure I can save the session, like during a shopping cart update.

sanmai
  • 29,083
  • 12
  • 64
  • 76