phpredis session locking -- 获取锁失败抛出 php notice -- would like fatal error
phpredis session locking -- failing to get lock throws php notice -- would like fatal error
当使用 php redis 作为具有会话锁定的会话处理程序时,如果出现无法发生锁定的错误,则会抛出 php 通知并继续执行脚本。有没有办法将其配置为致命错误并且脚本根本不处理?
确保您遵循此文档声明:
Locking feature is currently only supported for Redis setup with
single master instance
如果您仍然有一些问题,那么可以使用 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
脚本结束信息:
Fatal error: Redis locking problem with notice msg: Undefined
variable: 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);
当使用 php redis 作为具有会话锁定的会话处理程序时,如果出现无法发生锁定的错误,则会抛出 php 通知并继续执行脚本。有没有办法将其配置为致命错误并且脚本根本不处理?
确保您遵循此文档声明:
Locking feature is currently only supported for Redis setup with single master instance
如果您仍然有一些问题,那么可以使用 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
脚本结束信息:
Fatal error: Redis locking problem with notice msg: Undefined variable: 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);