skip to Main Content

When using php redis as a session handler with session locking if there is an error where a lock cannot happen a php notice is thrown and the script continues. Is there a way to configure it for a fatal error and the script NOT process at all?

2

Answers


  1. Chosen as BEST ANSWER

    In case anyone wants to know the exact code for turning session_lock notice into fatal error; here it is. (I couldn't have done it without the other answer, but this is exactly what I used)

    function redisNoticeFunction($errno, $errstr, $errfile, $errline, array $errcontext) 
    {
        // is the error E_NOTICE?
        if ($errno === E_NOTICE) 
        {
            // if error was suppressed with the @-operator
            if (0 === error_reporting()) 
            {
                // do nothing, continue execution of script
                return;
            }
        
            // if notice was about about Redis locking
            if ($errstr == 'session_start(): Acquire of session lock was not successful') 
            {
                $error_msg = 'Redis locking problem with notice msg: ' . $errstr;
                $error_msg .= ' at ' . $errfile . ':' . $errline . PHP_EOL;
    
                // signal fatal error
                $error_type = E_USER_ERROR;
                trigger_error ($error_msg, $error_type);
            }
            return;
        }
    }
    
    $current_error_reporting = error_reporting();
    error_reporting(E_ALL);
    set_error_handler('redisNoticeFunction');
    
    
    session_start();
    //Use regular error handling if session_start() does not end in a lock
    restore_error_handler();
    error_reporting($current_error_reporting);
    

  2. Make sure that you follow this documentation statement:

    Locking feature is currently only supported for Redis setup with
    single master instance

    If you still have some problems then a quick fix for whole application could be set your own error handler with set_error_handler that takes care for that particular problem.
    An example handler below that reacts only to using not declared variable. Change the regex pattern so it matches your Redis error msg.

    <?php
    
    error_reporting(E_ALL);
    
    $redisNoticeFunction = function($errno, $errstr, $errfile, $errline, array $errcontext) {
    
        // is the error E_NOTICE?
        if ($errno === E_NOTICE) {
                
            // if error was suppressed with the @-operator
            if (0 === error_reporting()) {
                // do nothing, continue execution of script
                return;
            }
            
            // check if notice is about Redis
            $pattern = '/.*Undefined variable.*/'; // <== change pattern so it matches notice about Redis
            $subject = $errstr;
            $status = preg_match($pattern, $subject);
            
            // if there was a problem with regex
            if (false === $status) {
                $msg = 'Could not perform preg_math with pattern: ' . $pattern . ' and subject: ' . $subject . PHP_EOL;
                // exit by throwing an exception
                throw new InvalidArgumentException($msg);
            }
    
            // if notice was about about Redis
            if ($status) {
                $error_msg = 'Redis locking problem with notice msg: ' . $errstr;
                $error_msg .= ' at ' . $errfile . ':' . $errline . PHP_EOL;
                
                // signal fatal error
                $error_type = E_USER_ERROR;
                trigger_error ($error_msg, $error_type);
                
                // or throw exception (comment above line with trigger_error())
                throw new RuntimeException($error_msg);
            }
    
            // the notice was not related to the Redis
            // echo its message and continue script
            echo $errstr . PHP_EOL;
            return;
        }
    
        // the error was not the E_NOTICE
        // do other error handling if needed
    
        // or just end the script
        die;
    
    };
    
    set_error_handler($redisNoticeFunction);    
    
    echo @ $notDeclared; // does not end script
    
    echo $notDeclared; // end script or throws an exception
    

    the last line

    echo $notDeclared; // end script or throws an exception
    

    ends script with info:

    Fatal error: Redis locking problem with notice msg: Undefined
    variable: notDeclared at /tmp/index.php:59

    set_error_handler should be used at the beginning of your php script (perfectly inside a common file that is required everywhere like a bootstrap.php)

    The downside of using your own error handler is that if you work with a framework or other wrapping code it might already set its own error handler that provides some useful features like debugging or maybe even that error handler is essential to that framework error handling, logging etc.

    If you wish to restore to original error handler (that default from PHP or the one that was set before your own) use restore_error_handler

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search