Skip to content
This repository has been archived by the owner on Mar 27, 2019. It is now read-only.

Commit

Permalink
Merge branch 'release/2.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
ezzatron committed Apr 19, 2016
2 parents f00c6cb + 6a4bbab commit 2c46904
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 172 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Asplode changelog

## 2.2.0 (2016-04-19)

- **[IMPROVED]** Increased the amount of memory reserved by the fatal error
handler, to improve the chances of catching memory exhausted fatals.

## 2.1.0 (2015-12-11)

- **[IMPROVED]** Error exceptions use file and line from the original error, and
Expand Down
22 changes: 14 additions & 8 deletions src/Asplode.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@ abstract class Asplode
* Installs a new error handler, and a new fatal error handler
* simultaneously.
*
* @param Isolator|null $isolator The isolator to use.
* @param integer $reservedMemory The amount of memory to reserve for fatal error handling.
* @param Isolator|null $isolator The isolator to use.
*
* @return tuple<ErrorHandlerInterface,FatalErrorHandlerInterface> A tuple containing the installed error handler and fatal error handler.
* @throws ErrorHandlingConfigurationException If the error reporting level is incorrectly configured.
*/
public static function install(Isolator $isolator = null)
{
$fatalHandler = static::installFatalHandler($isolator);
public static function install(
$reservedMemory = 1048576,
Isolator $isolator = null
) {
$fatalHandler = static::installFatalHandler($reservedMemory, $isolator);

return array(static::installErrorHandler($isolator), $fatalHandler);
}
Expand All @@ -58,14 +61,17 @@ public static function installErrorHandler(Isolator $isolator = null)
* This handler will, on shutdown, detect any installed exception handler,
* and pass an exception representing any fatal errors to said handler.
*
* @param Isolator|null $isolator The isolator to use.
* @param integer $reservedMemory The amount of memory to reserve for fatal error handling.
* @param Isolator|null $isolator The isolator to use.
*
* @return FatalErrorHandlerInterface The installed fatal error handler.
*/
public static function installFatalHandler(Isolator $isolator = null)
{
public static function installFatalHandler(
$reservedMemory = 1048576,
Isolator $isolator = null
) {
$handler = new FatalErrorHandler(null, $isolator);
$handler->install();
$handler->install($reservedMemory);

return $handler;
}
Expand Down
25 changes: 9 additions & 16 deletions src/ErrorHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public function __construct(
Isolator $isolator = null
) {
$this->isolator = Isolator::get($isolator);

if (null === $stack) {
$stack = new ErrorHandlerStack($isolator);
}
Expand Down Expand Up @@ -93,14 +94,15 @@ public function fallbackHandler()
*/
public function install()
{
if (0 === $this->isolator()->error_reporting()) {
if (0 === $this->isolator->error_reporting()) {
throw new ErrorHandlingConfigurationException();
}

if ($this->isInstalled()) {
throw new AlreadyInstalledException();
}

$this->stack()->push($this);
$this->stack->push($this);
}

/**
Expand All @@ -110,10 +112,11 @@ public function install()
*/
public function uninstall()
{
$handler = $this->stack()->pop();
$handler = $this->stack->pop();

if ($handler !== $this) {
if (null !== $handler) {
$this->stack()->push($handler);
$this->stack->push($handler);
}

throw new NotInstalledException();
Expand All @@ -127,7 +130,7 @@ public function uninstall()
*/
public function isInstalled()
{
return $this->stack()->handler() === $this;
return $this->stack->handler() === $this;
}

/**
Expand All @@ -146,7 +149,7 @@ public function handle($severity, $message, $filename, $lineno)
if (
E_DEPRECATED === $severity ||
E_USER_DEPRECATED === $severity ||
0 === $this->isolator()->error_reporting()
0 === $this->isolator->error_reporting()
) {
$fallbackHandler = $this->fallbackHandler();

Expand All @@ -172,16 +175,6 @@ public function __invoke($severity, $message, $filename, $lineno)
return $this->handle($severity, $message, $filename, $lineno);
}

/**
* Get the isolator.
*
* @return Isolator The isolator.
*/
protected function isolator()
{
return $this->isolator;
}

private $stack;
private $fallbackHandler;
private $isolator;
Expand Down
129 changes: 27 additions & 102 deletions src/FatalErrorHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
namespace Eloquent\Asplode;

use Eloquent\Asplode\Error\FatalErrorException;
use Eloquent\Asplode\Error\FatalErrorExceptionInterface;
use Eloquent\Asplode\Exception\AlreadyInstalledException;
use Eloquent\Asplode\Exception\NotInstalledException;
use Eloquent\Asplode\HandlerStack\ExceptionHandlerStack;
Expand All @@ -35,12 +34,14 @@ public function __construct(
Isolator $isolator = null
) {
$this->isolator = Isolator::get($isolator);

if (null === $stack) {
$stack = new ExceptionHandlerStack($isolator);
}

$this->stack = $stack;
$this->isEnabled = $this->isRegistered = false;
$this->isRegistered = false;
$this->isEnabled = false;
}

/**
Expand All @@ -56,17 +57,22 @@ public function stack()
/**
* Installs this fatal error handler.
*
* @param integer $reservedMemory The amount of memory to reserve for fatal error handling.
*
* @throws AlreadyInstalledException If this fatal error handler is already installed.
*/
public function install()
public function install($reservedMemory = 1048576)
{
if ($this->isInstalled()) {
if ($this->isEnabled) {
throw new AlreadyInstalledException();
}

if (!$this->isRegistered()) {
$this->beforeRegister();
$this->isolator()->register_shutdown_function($this);
if (!$this->isRegistered) {
$this->reservedMemory =
$this->isolator->str_repeat(' ', $reservedMemory);
$this->isolator
->class_exists('Eloquent\Asplode\Error\FatalErrorException');
$this->isolator->register_shutdown_function($this);
$this->isRegistered = true;
}

Expand All @@ -80,7 +86,7 @@ public function install()
*/
public function uninstall()
{
if (!$this->isInstalled()) {
if (!$this->isEnabled) {
throw new NotInstalledException();
}

Expand All @@ -94,7 +100,7 @@ public function uninstall()
*/
public function isInstalled()
{
return $this->isRegistered() && $this->isEnabled();
return $this->isRegistered && $this->isEnabled;
}

/**
Expand All @@ -107,17 +113,24 @@ public function isInstalled()
*/
public function handle()
{
if (!$this->isEnabled()) {
if (!$this->isEnabled) {
return;
}

$error = $this->isolator()->error_get_last();
$this->reservedMemory = '';
$error = $this->isolator->error_get_last();

if (null === $error) {
return;
}

$this->freeMemory();
$this->handleFatalError(
$handler = $this->stack->handler();

if (null === $handler) {
return;
}

$handler(
new FatalErrorException(
$error['message'],
$error['type'],
Expand All @@ -137,95 +150,7 @@ public function handle()
*/
public function __invoke()
{
return $this->handle();
}

/**
* Returns true if this handler is registered.
*
* @return boolean True if this handler is registered.
*/
protected function isRegistered()
{
return $this->isRegistered;
}

/**
* Returns true if this handler is enabled.
*
* @return boolean True if this handler is enabled.
*/
protected function isEnabled()
{
return $this->isEnabled;
}

/**
* Get the isolator.
*
* @return Isolator The isolator.
*/
protected function isolator()
{
return $this->isolator;
}

/**
* This method is called just before the shutdown function is registered.
*/
protected function beforeRegister()
{
$this->loadClasses();
$this->reserveMemory();
}

/**
* Pre-loads any classes or interfaces required in the event of a fatal
* error.
*/
protected function loadClasses()
{
$this->isolator()
->class_exists('Eloquent\Asplode\Error\FatalErrorException');
}

/**
* Reserves an amount of memory for use in the case of an out-of-memory
* fatal error.
*
* @param integer|null $size The amount of memory to reserve.
*/
protected function reserveMemory($size = null)
{
if (null === $size) {
$size = 10240;
}

$this->reservedMemory = $this->isolator()->str_repeat(' ', $size);
}

/**
* Frees the previously reseverd memory.
*/
protected function freeMemory()
{
$this->reservedMemory = '';
}

/**
* Handles PHP fatal errors.
*
* @param FatalErrorExceptionInterface $error The fatal error to handle.
*/
protected function handleFatalError(FatalErrorExceptionInterface $error)
{
$handler = $this->stack()->handler();

if (null === $handler) {
return;
}

$handler($error);
$this->handle();
}

private $stack;
Expand Down
4 changes: 3 additions & 1 deletion src/FatalErrorHandlerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ interface FatalErrorHandlerInterface
/**
* Installs this fatal error handler.
*
* @param integer $reservedMemory The amount of memory to reserve for fatal error handling.
*
* @throws AlreadyInstalledException If this fatal error handler is already installed.
*/
public function install();
public function install($reservedMemory = 1048576);

/**
* Uninstalls this fatal error handler.
Expand Down
16 changes: 5 additions & 11 deletions src/HandlerStack/AbstractHandlerStack.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public function __construct(Isolator $isolator = null)
public function handler()
{
$handler = $this->pop();

if (null !== $handler) {
$this->push($handler);
}
Expand Down Expand Up @@ -74,6 +75,7 @@ public function pushAll(array $handlers)
public function clear()
{
$handlers = array();

while (null !== ($handler = $this->pop())) {
$handlers[] = $handler;
}
Expand Down Expand Up @@ -108,11 +110,13 @@ public function restore(array $handlers)
public function executeWith($callable, $handler = null)
{
$handlers = $this->clear();

if (null !== $handler) {
$this->push($handler);
}

$error = null;

try {
$result = $callable();
} catch (Exception $error) {
Expand All @@ -128,15 +132,5 @@ public function executeWith($callable, $handler = null)
return $result;
}

/**
* Get the isolator.
*
* @return Isolator The isolator.
*/
protected function isolator()
{
return $this->isolator;
}

private $isolator;
protected $isolator;
}
Loading

0 comments on commit 2c46904

Please sign in to comment.