Fix #19402: Add shutdown event and fix working directory in yii\base\ErrorHandler

This commit is contained in:
Anton
2022-06-01 10:38:27 +03:00
committed by GitHub
parent a345649871
commit c1801c7c61
2 changed files with 32 additions and 1 deletions

View File

@ -28,6 +28,7 @@ Yii Framework 2 Change Log
- Bug #19368: Fix PHP 8.1 error when `$fileMimeType` is `null` in `yii\validators\FileValidator::validateMimeType()` (bizley) - Bug #19368: Fix PHP 8.1 error when `$fileMimeType` is `null` in `yii\validators\FileValidator::validateMimeType()` (bizley)
- Enh #19384: Normalize `setBodyParams()` and `getBodyParam()` in `yii\web\Request` (WinterSilence, albertborsos) - Enh #19384: Normalize `setBodyParams()` and `getBodyParam()` in `yii\web\Request` (WinterSilence, albertborsos)
- Bug #19386: Fix recursive calling `yii\helpers\BaseArrayHelper::htmlDecode()` (WinterSilence) - Bug #19386: Fix recursive calling `yii\helpers\BaseArrayHelper::htmlDecode()` (WinterSilence)
- Bug #19402: Add shutdown event and fix working directory in `yii\base\ErrorHandler` (WinterSilence)
- Enh #19416: Update and improve configurations for `yii\console\controllers\MessageController` (WinterSilence) - Enh #19416: Update and improve configurations for `yii\console\controllers\MessageController` (WinterSilence)

View File

@ -26,6 +26,12 @@ use yii\web\HttpException;
*/ */
abstract class ErrorHandler extends Component abstract class ErrorHandler extends Component
{ {
/**
* @event Event an event that is triggered when the handler is called by shutdown function via [[handleFatalError()]].
* @since 2.0.46
*/
const EVENT_SHUTDOWN = 'shutdown';
/** /**
* @var bool whether to discard any existing page output before error display. Defaults to true. * @var bool whether to discard any existing page output before error display. Defaults to true.
*/ */
@ -60,6 +66,10 @@ abstract class ErrorHandler extends Component
* @var bool whether this instance has been registered using `register()` * @var bool whether this instance has been registered using `register()`
*/ */
private $_registered = false; private $_registered = false;
/**
* @var string the current working directory
*/
private $_workingDirectory;
public function init() public function init()
@ -70,6 +80,7 @@ abstract class ErrorHandler extends Component
/** /**
* Register this error handler. * Register this error handler.
*
* @since 2.0.32 this will not do anything if the error handler was already registered * @since 2.0.32 this will not do anything if the error handler was already registered
*/ */
public function register() public function register()
@ -83,7 +94,11 @@ abstract class ErrorHandler extends Component
set_error_handler([$this, 'handleError']); set_error_handler([$this, 'handleError']);
} }
if ($this->memoryReserveSize > 0) { if ($this->memoryReserveSize > 0) {
$this->_memoryReserve = str_repeat('x', $this->memoryReserveSize); $this->_memoryReserve = str_pad('', $this->memoryReserveSize, 'x');
}
// to restore working directory in shutdown handler
if (PHP_SAPI !== 'cli') {
$this->_workingDirectory = getcwd();
} }
register_shutdown_function([$this, 'handleFatalError']); register_shutdown_function([$this, 'handleFatalError']);
$this->_registered = true; $this->_registered = true;
@ -97,6 +112,8 @@ abstract class ErrorHandler extends Component
public function unregister() public function unregister()
{ {
if ($this->_registered) { if ($this->_registered) {
$this->_memoryReserve = null;
$this->_workingDirectory = null;
restore_error_handler(); restore_error_handler();
restore_exception_handler(); restore_exception_handler();
$this->_registered = false; $this->_registered = false;
@ -264,6 +281,13 @@ abstract class ErrorHandler extends Component
{ {
unset($this->_memoryReserve); unset($this->_memoryReserve);
if (isset($this->_workingDirectory)) {
// fix working directory for some Web servers e.g. Apache
chdir($this->_workingDirectory);
// flush memory
unset($this->_workingDirectory);
}
// load ErrorException manually here because autoloading them will not work // load ErrorException manually here because autoloading them will not work
// when error occurs while autoloading a class // when error occurs while autoloading a class
if (!class_exists('yii\\base\\ErrorException', false)) { if (!class_exists('yii\\base\\ErrorException', false)) {
@ -279,6 +303,7 @@ abstract class ErrorHandler extends Component
$exception = new ErrorException($error['message'], $error['type'], $error['type'], $error['file'], $error['line']); $exception = new ErrorException($error['message'], $error['type'], $error['type'], $error['file'], $error['line']);
} }
$this->exception = $exception; $this->exception = $exception;
unset($error);
$this->logException($exception); $this->logException($exception);
@ -286,12 +311,16 @@ abstract class ErrorHandler extends Component
$this->clearOutput(); $this->clearOutput();
} }
$this->renderException($exception); $this->renderException($exception);
unset($exception);
// need to explicitly flush logs because exit() next will terminate the app immediately // need to explicitly flush logs because exit() next will terminate the app immediately
Yii::getLogger()->flush(true); Yii::getLogger()->flush(true);
if (defined('HHVM_VERSION')) { if (defined('HHVM_VERSION')) {
flush(); flush();
} }
$this->trigger(static::EVENT_SHUTDOWN);
exit(1); exit(1);
} }
} }
@ -337,6 +366,7 @@ abstract class ErrorHandler extends Component
* This method can be used to convert exceptions inside of methods like `__toString()` * This method can be used to convert exceptions inside of methods like `__toString()`
* to PHP errors because exceptions cannot be thrown inside of them. * to PHP errors because exceptions cannot be thrown inside of them.
* @param \Throwable $exception the exception to convert to a PHP error. * @param \Throwable $exception the exception to convert to a PHP error.
* @return never
*/ */
public static function convertExceptionToError($exception) public static function convertExceptionToError($exception)
{ {