Question

Do you know any solution to recover from the PHP fatal error : "Allowed memory size ... exhausted"

I have a shutdown function that is called when a fatal error appear. This function create an ErrorException from it, and logs it.

The problem is : when there is no more memory available, it can't log the error (I log in Firebug, via FirePHP, with Zend Framework).

So what i mean by "how to recover from it", is how to perform basic error log, and let Zend Framework send the Headers, so that the error is logged (in Firebug in my case) as any other error ?

Thanks

Was it helpful?

Solution

This error is a fatal error - that means you cannot recover from it. If PHP has hit it's memory limit, it won't be able to allocate any more memory to create your exception and any other memory it needs to carry on its execution.

There is another type of error - "catchable fatal error" which as the name suggests, can be caught in a try/catch, but unfortunately the memory size allocation is not one of them.

OTHER TIPS

if((memory_get_usage() / 1024 /1024) < 70)

I simply divide the memory_get_usage by 1024 squared to compare it to a 'normal' megabyte value of '70'.

I ran into memory problems with php inside a for loop and wrote this simple if statement to prevent my script from setting off a fatal error. In addition, the server I was operating on didn't allow me to modify the memory limit (this is often the case in some cloud offerings like openshift or large web hosts like dreamhost.) I didn't really notice any serious performance degradations (in php 5.3 which may handles functions such as this slightly differently than php 4.x or 5.x... at any rate the performance implication of a script giving a fatal error outweighs any overhead the function call may force. And would also prevent a runaway script from consuming all available ram.

Many may argue; oh hey your software isn't optimized. Yes. You're probably right; but with complex data sets you can only squeeze so much performance out before you need to throw more memory at it; and hunting down memory errors in an ajax flow can be very frustrating; especially when you aren't sure where your log files are.

The regular way to customize error handling is through

set_error_handler — Sets a user-defined error handler function

The docs for this function state (emphasis mine):

The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.

So, it won't work regularly, but you can try

As of PHP7, Errors and Exceptions are Throwables, so you can try/catch them:

PHP errors are sent by default to your apache error log /path/to/apache/logs/error.log and you can see it there.

Got an idea for an untested trick and I'd be happy to know if it helped. Allocate some global variable when you first register the shutdown function and release it when the shutdown function's code is first executed. You may then have sufficient memory to create the Exception object. Let me know if it worked and please publish the code here.

This worked fine for me:

try {
    ini_set('memory_limit', (ini_get('memory_limit')+1).'M');
} catch(Exception $e) {}

This assumes your memory limit is in the format 123M.

One I can think of is that you when you're doing your memory intensive operation you manually query memory_get_usage() on a regular basis (e.g. every loop iteration) and dump out your headers/error when it goes over some failsafe value which is below the script limit. It will slow your script down a lot, but at least you'll get something back.

Or, and you may not be able to do this, run the memory intensive stuff as a CLI-based script called from inside your web-based stuff by using exec. The CLI part might fall over, but the web part will be able to report on it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top