簡體   English   中英

phpredis 會話鎖定——無法獲得鎖定會引發 php 通知——想要致命錯誤

[英]phpredis session locking -- failing to get lock throws php notice -- would like fatal error

當使用php redis作為具有會話鎖定的會話處理程序時,如果出現無法發生鎖定的錯誤,則會拋出 php 通知並繼續執行腳本。 有沒有辦法將它配置為致命錯誤並且腳本根本不處理?

確保您遵循此文檔聲明:

鎖定功能目前僅支持具有單個主實例的Redis 設置

如果您仍然有一些問題,那么可以使用set_error_handler設置您自己的錯誤處理程序來快速修復整個應用程序,以解決該特定問題。 下面的示例處理程序僅對使用未聲明的變量做出反應。 更改正則表達式模式,使其與您的 Redis 錯誤消息匹配。

<?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

最后一行

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

用信息結束腳本:

致命錯誤:Redis 鎖定問題,通知 msg:未定義變量:notDeclared at /tmp/index.php:59

set_error_handler應該在你的 php 腳本的開頭使用(完全在一個公共文件中,這個文件到處都需要,比如 bootstrap.php)

使用自己的錯誤處理程序的缺點是,如果您使用框架或其他包裝代碼,它可能已經設置了自己的錯誤處理程序,提供了一些有用的功能,例如調試,或者甚至錯誤處理程序對於該框架錯誤處理、日志記錄是必不可少的等等。

如果您希望恢復到原始錯誤處理程序(來自 PHP 的默認處理程序或您自己之前設置的錯誤處理程序),請使用restore_error_handler

如果有人想知道將 session_lock 通知轉換為致命錯誤的確切代碼; 這里是。 (如果沒有其他答案,我無法做到,但這正是我使用的)

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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM