Skip to content

Commit

Permalink
Merge branch '3.2-fatal-memory-handling' into 3.2
Browse files Browse the repository at this point in the history
Forward port the changes from 2.8 into 3.x allowing the memory limit to
be increased when fatal errors happen. Increasing the memory limit
allows logging and other error handling behavior to be executed when the
memory limit has been exhausted.

Refs #7550
  • Loading branch information
markstory committed Dec 28, 2015
2 parents dd659e2 + 0c541b7 commit 282f6c8
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
39 changes: 38 additions & 1 deletion src/Error/BaseErrorHandler.php
Expand Up @@ -72,6 +72,13 @@ public function register()
if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg')) {
return;
}
$megabytes = Configure::read('Error.extraFatalErrorMemory');
if ($megabytes === null) {
$megabytes = 4;
}
if ($megabytes > 0) {
$this->increaseMemoryLimit($megabytes * 1024);
}
$error = error_get_last();
if (!is_array($error)) {
return;
Expand All @@ -86,7 +93,7 @@ public function register()
}
$this->handleFatalError(
$error['type'],
$error['message'],
$error['message'],
$error['file'],
$error['line']
);
Expand Down Expand Up @@ -212,6 +219,36 @@ public function handleFatalError($code, $description, $file, $line)
return true;
}

/**
* Increases the PHP "memory_limit" ini setting by the specified amount
* in kilobytes
*
* @param string $additionalKb Number in kilobytes
* @return void
*/
public function increaseMemoryLimit($additionalKb)
{
$limit = ini_get('memory_limit');
if (!strlen($limit) || $limit === '-1') {
return;
}
$limit = trim($limit);
$units = strtoupper(substr($limit, -1));
$current = substr($limit, 0, strlen($limit) - 1);
if ($units === 'M') {
$current = $current * 1024;
$units = 'K';
}
if ($units === 'G') {
$current = $current * 1024 * 1024;
$units = 'K';
}

if ($units === 'K') {
ini_set('memory_limit', ceil($current + $additionalKb) . 'K');
}
}

/**
* Log an error.
*
Expand Down
37 changes: 37 additions & 0 deletions tests/TestCase/Error/ErrorHandlerTest.php
Expand Up @@ -433,4 +433,41 @@ public function testHandlePHP7Error()
$errorHandler->handleException($error);
$this->assertContains('Unexpected variable foo', $errorHandler->response->body(), 'message missing.');
}

/**
* Data provider for memory limit changing.
*
* @return array
*/
public function memoryLimitProvider()
{
return [
// start, adjust, expected
['256M', 4, '262148K'],
['262144K', 4, '262148K'],
['1G', 128, '1048704K'],
];
}

/**
* Test increasing the memory limit.
*
* @dataProvider memoryLimitProvider
* @return void
*/
public function testIncreaseMemoryLimit($start, $adjust, $expected)
{
$initial = ini_get('memory_limit');
$this->skipIf(strlen($initial) === 0, 'Cannot read memory limit, and cannot test increasing it.');

// phpunit.xml often has -1 as memory limit
ini_set('memory_limit', $start);

$errorHandler = new TestErrorHandler();
$this->assertNull($errorHandler->increaseMemoryLimit($adjust));
$new = ini_get('memory_limit');
$this->assertEquals($expected, $new, 'memory limit did not get increased.');

ini_set('memory_limit', $initial);
}
}

0 comments on commit 282f6c8

Please sign in to comment.