Safely catch a 'Allowed memory size exhausted' error in PHP

Related searches

I have a gateway script that returns JSON back to the client. In the script I use set_error_handler to catch errors and still have a formatted return.

It is subject to 'Allowed memory size exhausted' errors, but rather than increase the memory limit with something like ini_set('memory_limit', '19T'), I just want to return that the user should try something else because it used to much memory.

Are there any good ways to catch fatal errors?

As this answer suggests, you can use register_shutdown_function() to register a callback that'll check error_get_last().

You'll still have to manage the output generated from the offending code, whether by the @ (shut up) operator, or ini_set('display_errors', false)

ini_set('display_errors', false);

error_reporting(-1);

set_error_handler(function($code, $string, $file, $line){
        throw new ErrorException($string, null, $code, $file, $line);
    });

register_shutdown_function(function(){
        $error = error_get_last();
        if(null !== $error)
        {
            echo 'Caught at shutdown';
        }
    });

try
{
    while(true)
    {
        $data .= str_repeat('#', PHP_INT_MAX);
    }
}
catch(\Exception $exception)
{
    echo 'Caught in try/catch';
}

When run, this outputs Caught at shutdown. Unfortunately, the ErrorException exception object isn't thrown because the fatal error triggers script termination, subsequently caught only in the shutdown function.

You can check the $error array in the shutdown function for details on the cause, and respond accordingly. One suggestion could be reissuing the request back against your web application (at a different address, or with different parameters of course) and return the captured response.

I recommend keeping error_reporting() high (a value of -1) though, and using (as others have suggested) error handling for everything else with set_error_handler() and ErrorException.

Safe Catch Seafood, In this post, we will discuss how we keep our chickens and eggs safe from predators, and how we captured and safely disposed of a skunk using a live trap. Fortify� Read Customer Reviews & Find Best Sellers. Free 2-Day Shipping w/Amazon Prime.

If you need to execute business code when this error happens (logging, backup of the context for future debugs, emailing or such), registering a shutdown function is not enough: you should free memory in a way.

One solution is to allocate some emergency memory somewhere:

public function initErrorHandler()
{
    // This storage is freed on error (case of allowed memory exhausted)
    $this->memory = str_repeat('*', 1024 * 1024);

    register_shutdown_function(function()
    {
        $this->memory = null;
        if ((!is_null($err = error_get_last())) && (!in_array($err['type'], array (E_NOTICE, E_WARNING))))
        {
           // $this->emergencyMethod($err);
        }
    });
    return $this;
}

How to Safely Catch a Skunk Without Getting Sprayed – The , The New York State Health Department produced this video to urge New Yorkers to avoid the risk Duration: 1:24 Posted: Jul 1, 2008 In firearms, a safety or safety catch is a mechanism used to help prevent the accidental discharge of a firearm, helping to ensure safer handling. Safeties can generally be divided into subtypes such as internal safeties and external safeties. Sometimes these are called "passive" and "active" safeties, respectively. Firearms with the ability to allow the user to select various fire modes may have separate switches for safety and for mode selection or may have the safety integrated with the mode

you could get the size of the memory already consumed by the process by using this function memory_get_peak_usage documentations are at http://www.php.net/manual/en/function.memory-get-peak-usage.php I think it would be easier if you could add a condition to redirect or stop the process before the memory limit is almost reached by the process. :)

How to Safely Catch a Bat, Before visiting a park, please check the park website to determine its operating status. Updates about the overall NPS response to COVID-19,� Safe Catch tests every fish for mercury. Sustainably wild caught. Cooked to retain all nutrients and flavor. Canned seafood like you've never tasted before.

While @alain-tiemblo solution works perfectly, I put this script to show how you can reserve some memory in a php script, out of object scope.

Short Version
// memory is an object and it is passed by reference
function shutdown($memory) {
    // unsetting $memory does not free up memory
    // I also tried unsetting a global variable which did not free up the memory
    unset($memory->reserve);
}

$memory = new stdClass();
// reserve 3 mega bytes
$memory->reserve = str_repeat('❤', 1024 * 1024);

register_shutdown_function('shutdown', $memory);
Full Sample Script
<?php

function getMemory(){
    return ((int) (memory_get_usage() / 1024)) . 'KB';
}

// memory is an object and it is passed by reference
function shutdown($memory) {
    echo 'Start Shut Down: ' . getMemory() . PHP_EOL;

    // unsetting $memory does not free up memory
    // I also tried unsetting a global variable which did not free up the memory
    unset($memory->reserve);

    echo 'End Shut Down: ' . getMemory() . PHP_EOL;
}

echo 'Start: ' . getMemory() . PHP_EOL;

$memory = new stdClass();
// reserve 3 mega bytes
$memory->reserve = str_repeat('❤', 1024 * 1024);

echo 'After Reserving: ' . getMemory() . PHP_EOL;

unset($memory);

echo 'After Unsetting: ' . getMemory() . PHP_EOL;

$memory = new stdClass();
// reserve 3 mega bytes
$memory->reserve = str_repeat('❤', 1024 * 1024);

echo 'After Reserving again: ' . getMemory() . PHP_EOL;

// passing $memory object to shut down function
register_shutdown_function('shutdown', $memory);

And the output would be:

Start: 349KB
After Reserving: 3426KB
After Unsetting: 349KB
After Reserving again: 3426KB
Start Shut Down: 3420KB
End Shut Down: 344KB

How to Safely Catch and Release, By placing a dark towel over the trap, without blocking the door, you create a space that looks dark, hidden, and safe to cats. Try a more exciting bait. Something� Safe Catch only uses fish that are tested and pass the strict limits defined below: 0.1 ppm for Safe Catch Elite which is 10x lower than the FDA limit of 1.00 ppm. 0.1 ppm for Safe Catch Ahi Wild Yellowfin Tuna which is 10x lower than the FDA limit of 1.00 ppm. 0.1 ppm for Safe Catch Wild Sardines which is 10x lower than the FDA limit of 1.00 ppm.

Tips for How to Catch a Hard to Trap Feral or Stray Cat, How to Safely Catch a Snake Step 1: Pinning. Snake sticks have a flat head which can be effectively used to pin down a snake before it manages to Step 2: Lifting (Hook Stick Only) Step 1. The one way to catch a snake is to lift it up in the middle. Start by moving Step 3: Lifting (Hook Stick

DO safely trap them in an area like a yard if possible. Be careful not to corner them as if they are scared this could cause them to lash out. DO play with a ball or frisbee, but ignore the dog. They may approach in hopes of some playtime. DO leave out food, their bed, a t shirt or something of yours that will smell like you.

The hilarious viral video of an Irish family's attempt to catch one of these flying critters in their kitchen left us wondering: what should you do if a bat finds its way into your house?

Comments
  • +1 for general aptitude in the face of wanton incorrectness :)
  • In case this is a problem for anyone else, it's worth bearing in mind that register_shutdown_function loses your call stack when it's called. So you can't really use it to work out where your memory error happened.
  • @ChrisRae if you've got xdebug enhabled, xdebug_get_function_stack(), is a debug_backtrace alternative that will have the entire trace
  • I thought this sounded completely stupid when I read it - I thought "surely some kind of cleanup would happen between when PHP runs out of memory and when it calls the shutdown function, and you wouldn't have to worry about that... ". I was very wrong. Thank you so much for taking the time to post this - very helpful!
  • One thing to know is that your check array (E_NOTICE, E_WARNING) will actually catch depreciation notices and other unwanted minor issues. Some cases, you may want to rewrite to remove the ! negation and replace it with in_array($err['type'], array (E_ERROR))
  • Fascinating. Working.
  • A slightly faster way to allocate memory is e.g. new SplFixedArray(65536);. Each empty array element consumes 16 bytes on my system.
  • Indeed, this is a way of catching the error before it happens. Allows for one to save status information on the ongoing task and possibly even resume it once redirected.
  • +1 -- I agree, managing the issue before it becomes an error is likely the best solution (and yields the most robust handling options) however, error "handling" for fatal errors has it's benefits too. A hybrid solution, managing memory status when possible, handling fatals when necessary, is likely the best approach to employ.
  • Sure, but script memory allocation errors are often too hard to predict, as PHP doesn't generally engage in smalltalk with us about its internal memory business, so we know little about what's going to be the memory cost of calling external libraries, DB queries, image manipulation, or just using big multi-dimensional arrays etc. At what exact load level to start the "preventive panicking", can only be guessed. (Sometimes still quite well, nevertheless.)
  • I came on similar problem of memory allocation but in different situation: uploaded image resizing some 10MB of jpeg grow fast to more than 100MB on RAM. i used this formula to apreciate the RAM needed: $width * $height * 4 * 1.5 + 1048576 from this site link. I dont know if it's optimal but it seems to work well (~70MB computed for some ~60MB really allocated by the image)
  • A slightly faster way to allocate memory is e.g. new SplFixedArray(65536);. Each empty array element consumes 16 bytes on my system.