Git viewing holonet/common / 5c101247095feb61653fef3bce105d314e1854f8


Filter

5c101247095feb61653fef3bce105d314e1854f8

Matthias Lantsch(3 years, 2 months ago)

Rework error handling to handle errors in production (without whoops) better

Browse Files
  • Changed file ErrorDispatcher.php
    diff --git a/e2e6fe6d1cbd9996b60262dc89f2cee900b0277e b/f1f13ce5f2b7ce470484c5c0707caa60e2a87e39
    index e2e6fe6..f1f13ce 100644
    --- a/e2e6fe6d1cbd9996b60262dc89f2cee900b0277e
    +++ b/f1f13ce5f2b7ce470484c5c0707caa60e2a87e39
    @@ -24,6 +24,11 @@ class ErrorDispatcher {
     	 */
     	private array $exceptionHandlers = array();
    
    +	/**
    +	 * @var ErrorHandler $finalHandler Last error handler to be called
    +	 */
    +	private ?ErrorHandler $finalHandler = null;
    +
     	/**
     	 * @var callable[] $shutdownHandlers
     	 */
    @@ -53,6 +58,10 @@ class ErrorDispatcher {
     			foreach ($this->errorHandlers as $handler) {
     				$handler(...$args);
     			}
    +
    +			if ($this->finalHandler !== null) {
    +				$this->finalHandler->handleError(...$args);
    +			}
     		});
    
     		/**
    @@ -63,6 +72,10 @@ class ErrorDispatcher {
     			foreach ($this->exceptionHandlers as $handler) {
     				$handler(...$args);
     			}
    +
    +			if ($this->finalHandler !== null) {
    +				$this->finalHandler->handleException(...$args);
    +			}
     		});
    
     		/**
    @@ -73,6 +86,14 @@ class ErrorDispatcher {
     			foreach ($this->shutdownHandlers as $handler) {
     				$handler(...$args);
     			}
    +
    +			if ($this->finalHandler !== null) {
    +				$this->finalHandler->handleShutdown(...$args);
    +			}
     		});
     	}
    +
    +	public function setFinalHandler(ErrorHandler $finalHandler): void {
    +		$this->finalHandler = $finalHandler;
    +	}
     }
  • Changed file ErrorHandler.php
    diff --git a/63f09dabbe2c79b34b800a12ce7f9c89b55282d6 b/4def0ee8dca6b0bd944667f2bbee599dfbe544ae
    index 63f09da..4def0ee 100644
    --- a/63f09dabbe2c79b34b800a12ce7f9c89b55282d6
    +++ b/4def0ee8dca6b0bd944667f2bbee599dfbe544ae
    @@ -39,7 +39,9 @@ class ErrorHandler {
     		\E_USER_DEPRECATED => array('level' => LogLevel::WARNING, 'name' => 'E_USER_DEPRECATED'),
     	);
    
    -	private ?LoggerInterface $logger;
    +	protected ?Throwable $lastException = null;
    +
    +	protected ?LoggerInterface $logger;
    
     	public function __construct(?LoggerInterface $logger = null) {
     		$this->logger = $logger;
    @@ -60,7 +62,7 @@ class ErrorHandler {
     			return null;
     		}
    
    -		list('type' => $type, 'name' => $name) = (self::ERROR_LEVEL_LOOKUP[$errno] ?? self::ERROR_LEVEL_LOOKUP[\E_ERROR]);
    +		list('level' => $type, 'name' => $name) = (self::ERROR_LEVEL_LOOKUP[$errno] ?? self::ERROR_LEVEL_LOOKUP[\E_ERROR]);
    
     		if ($this->logger !== null) {
     			$this->logger->log(
    @@ -95,6 +97,34 @@ class ErrorHandler {
     			$this->logger->log(LogLevel::ERROR, $message, array('exception' => $exception));
     		}
    
    -		exit(255);
    +		$this->lastException = $exception;
    +	}
    +
    +	/**
    +	 * Shutdown function
    +	 * should be changed in extending classes to add more functionality to it.
    +	 */
    +	public function handleShutdown(): void {
    +		if (($error = $this->getLastError()) !== null) {
    +			echo $error;
    +			exit(255);
    +		}
    +	}
    +
    +	/**
    +	 * Return the last error message if there was one.
    +	 * Can be used in fatal shutdown handlers to help.
    +	 */
    +	protected function getLastError(): ?string {
    +		if ($this->lastException !== null) {
    +			$class = get_class($this->lastException);
    +
    +			return "Unwanted crash due to {$class}: {$this->lastException->getMessage()}";
    +		}
    +		if (($lasterror = error_get_last()) !== null) {
    +			return "Unwanted crash due to: {$lasterror['message']} in file {$lasterror['file']} on line {$lasterror['line']}";
    +		}
    +
    +		return null;
     	}
     }