Setting custom error handler dramatically increases script execution time - php

I have a script in production - an ecommerce checkout page - that has had some errors in the past that have prevented it from working and have cost me money. I wanted to get notified on errors so I worked this up:
<?php
function mailErrorHandler($errno, $errstr)
{
echo "<!--PHP ERROR:";
echo "---[$errno] $errstr ---";
echo "-->";
error_log("Error: [$errno] $errstr",1,
"myemail#myserver.com","From: me#workserver.com");
}
set_error_handler("mailErrorHandler",E_ALL);
echo 1-thisisnotanumber;
?>
When I use it as-is in it's own script, it works and executes quickly. However, when I add it to my existing application, the page load time decreases DRAMATICALLY i.e. 40 seconds as opposed to <1 second. Can anyone think of a reason why this might be happening?

If you have a significant amount of traffic and you're throwing a LOT of errors, writing to the log can cause a significant amount of disk IO. This can slow down your app to the extent that you're talking about.
Maybe what you're throwing isn't errors, but rather a bunch of Notice "exceptions". If you have them set to not display (the default in most versions of PHP) and you're getting a boat load of them, you could be running your error handler hundreds and hundreds of times. Every time the handler is run, it has to do a trace, break out of the current scope, do all sorts of processing, and if that's all happening because you're using =& new with PHP 5.3 or trying to access undefined array elements (or any other common notice), you're going to see those kinds of delays.
So in order to fix this, the doctor prescribes turning off the error handler on your test server, turning on the display of notices, run through the flow and take note of any errors/notices/etc, then fix the aforementioned notices on your production box.
Hope this helps!

Hmm. When you say "use it on it's own", do you mean in a separate page that is invoked through Apache, or are you running it on the command line? The delay, combined with the use of email makes me suspect a DNS or network issue...something not resolving or not connecting and timing out.
Another thought...fire up Xdebug and do a profile dump while this is running and see if that sheds any light on what is taking all the time.

Try to add an exit() after the error_log() call.

An other solution would be to log to a file if you have problems with the error_hander:
Set
log_errors = On
html_errors = Off
error_log = log
in your php.ini, then all the errors will be logged into the default error.log of your server.

Related

PHP Script stops executing with many objects

i got a script which creates a list implementation of messages being sent between users.
Everything works fine, till the amount of messages rises up to about 77.000.
For every message a object will be created and every object has a reference to the next message object.
I enabled error reporting and increased the memory limit - I don't get any errors and the http status code is a 200 Ok, even if the developer console tells me that the request failed.
If you have verified that it is not a memory limit issue, this could be a limitation of PHP....similar to this question:
How to Avoid PHP Object Nesting/Creation Limit?
If you need to work with 77 000 objects in the same PHP script - it is something wrong with the architecture, php is not right choice for such calculations (even if it can handle this under some circumstances)
to track this particular error try to set in php.ini:
display_errors=1
display_startup_errors=1
error_reporting=-1
log_errors=1
memory_limit=to any reasonable value
max_input_time=to any reasonable value
max_execution_time=to any reasonable value
report_memleaks=1
error_log=writable path
consider using xdebug extension
don't forget to restart apache after changing proper php.ini (you can have different php.ini for apache and cli)
check if any set_error_handler or set_exception_handler functions are called in your code

PHP task terminated but no error condition raised

A PHP script is using the ZipArchive class and is potentially long running.
Since it is dying silently but writing a partial zip file, I wrapped error_log() statements around the $zip->close(). (ini_set sets error logging to a file and E_ALL just before this code)
error_log("calling zip->close()");
$rc = $zip->close();
error_log("zip->close() returned $rc");
The logging file shows the first error_log, but never the second.
A unix top command shows the process running for a total CPU time of c. 2.5 minutes before it goes defunct.
I have also tried trapping the error with set_error_handler(), and the handler using error_log() to record the catch. But nothing shows up in the log file.
I'm assuming the process is being bounced, maybe by Apache (I have no control over Apache or PHP).
My question is: why can't I see this error in the file being used by error_log?
Thanks for the suggestions for circumventing the problem, but my question remains:
Why can't I see this error in the log? Or why can't I catch this error via set_error_handler()?
set_time_limit(0);
0 = Indefinitely

php-error.log reports the same error multiple times

php-error.log keeps reporting the same error multiple times. Seems like with every browser request. Caching is disabled on most pages as this is a dynamic site with user-generated content.
In php.ini, both ignore_repeated_errors and ignore_repeated_source are On.
Does anybody have any ideas to fix this?
Thank you in advance
PHP log will not ignore repeated errors with ignore_repeated_errors = On - It will happen per script execution (so normally yes...per request). How are you running PHP (mod_php, fastcgi,...)? The best option would be to filter the log afterwards, but if you really want to get in there earlier you could use something like a cache that's passed through with the error message and only logged if there's a cache miss.
Or if you're running a typical LAMP stack you could use a db table for logging and only insert the new line if a recent one doesn't exist.

Php script stops after long time and no error could be found on the error_log

Im running a long php script which handles large amounts of data.
The problem is that the script suddenly stops and no exception is thrown or could be found on the error_log.
I have set the display_errors and the error_logging to 1 in the .ini config file.
Few more details:
1) The scripts executes the 'file_get_contents' function for many times.
2) The scripts contains recursion when the file_get_contents fails.
Any help would be appriciated.
It might have hit the max execution time.
set_time_limit(0); // to increase the timelimit to infinity
Error loging configs are different depending on your hosting environment. I'd first verify that you're editing the right php.ini file. Take a look at your phpinfo output and make sure that those params are indeed set and check the path/file for where errors are being logged to. Sometimes it goes to the apache error log, other times it can be sent to a dedicated php log. Are you able to get any error output if you purposefully create a syntax error? You might also consider looking in your syslog to see if there's anything there.

PHP produces a completely white page, no errors, logs, or headers.

While running some PHP code on my private WAMP PC I'm suddenly getting a blank response from the server - no response actually. No headers, no data, nothing in the PHP error logs, nada. I restarted APACHE and PHP but still nothing. I know php is working because I can access other PHP scripts just fine.
Firebug reports no headers, ? bytes, and it only takes 163ms to "load" (so it's not a timeout). I thought about rapid memory consumption - but I monitored my PC's memory and it's not showing any spikes. Errors and Exceptions have been working fine until now.
What in the world?
max_execution_time = 30 ;
max_input_time = 60 ;
max_input_nesting_level = 64 ;
memory_limit = 500M ;
error_reporting = E_ALL | E_NOTICE | E_STRICT
display_errors = On
log_errors = On
:EDIT:
I wouldn't touch # with a ten-foot-pole. I think the ruby guys throw that in there so programmers would drop PHP.
Anyway, I enabled xdebug and it didn't output any grind files. Then I took zombat's advice and placed a DIE() at the top of the page and it worked. I guess that I just have some very weird code that totally kills PHP. Even if errors were disabled or suppressed with # I should still be getting back a header from the server with the empty content!
If I find more I'll post back.
Run the page from a console and you'll get the error message.
// nix
php yourFile.php
// Windows
c:\path\to\php.exe yourFile.php
You could have a .htaccess file in this directory which has modified error reporting.
To test, try explicitly setting these options at the top of your php script which is giving you trouble.
ini_set('display_errors',1);
error_reporting(E_ALL);
I've also seen this caused by over-zealous anti-virus packages. Some contain web proxy software to filter internet and email. In that case, the page would just continue load into infinity but never complete.
You say other PHP scripts are working, so that indicates it's probably not an Apache problem. You also appear to have all your logging settings correct, and nothing is getting logged, so it's quite possible PHP is exiting normally before it outputs anything. One of the following could be true:
A misplaced exit() statement? You were working on the code, maybe you added a quick exit() to check something out, and forgot to remove it?
don.neufeld's idea of checking for the use of the # operator, which suppresses any error messages, has cost me hours of debugging time in the past. Definitely something to look for.
In situations like this, the poor man's debugging approach can yield some quick results. Throw an exit('wtf'); in as the first line in the script in question here. Does that run? The results of that test immediately rules out all sorts of possibilities no matter what the result is. If you don't get any output, then it's probably a server-level problem (configuration, bad module, etc), although be careful of any higher-level buffering. If you do get output, then you know the server is fine, and the issue lies deeper in your script, in which case you can move the exit() call down a few lines, rinse and repeat. Not an elegant way to debug, but it's quick and dirty, and you'll probably find the issue in a couple of minutes.
Beware the # (error suppression) operator, if you have a syntax error on a line with # PHP will silently exit.
To detect this condition, use set_error_handler and write your own error handler, you'll still get called for errors where # is used.
Check php.ini setting for short_open_tag = On or short_open_tag = Off
The most likely thing here is that apache is crashing. Look through the apache error log maybe, or attach a debugger.
Details on looking debugging the apache/php process on windows can be found at http://bugs.php.net/bugs-generating-backtrace-win32.php
I guessed the answer to this problem - it turns out that PHP 5.2.5 can't handle a recursive death.
<?php
class A
{
public function __construct()
{
new B;
}
}
class B
{
public function __construct()
{
new A;
}
}
new A;
print 'Loaded Class A';
No headers, errors, content, logs, xdebug dumps, memory spikes, CPU spikes, server crashes, or anything. After about 150ms PHP just "ends". Weird.
To activate error display in your PHP code in case you don't see anything, insert
ini_set('display_errors',1);
error_reporting(E_ALL);
Example where this potentialy saves you a lot of time:
This code in a joomla default.php template file displays a blank page with no error msg without lines 20 and 21
17 <?php if ($params->get('title_article_linkable')) { ?>
18 <a href="<?php
19 $url = JRoute::_(ContentHelperRoute::getArticleRoute($item->id,$item->catid));
20 ini_set('display_errors',1);
21 error_reporting(E_ALL);
22 echo $url; ?>">
23 <?php echo $this->item->title; ?></a> // should be $item->title !!
24 <?phpLL000000 } else { ?>
25 <?php echo $item->title; ?>
26 <?php } ?>
Output:
check the Event Log.
When this happens, it is usually worth cutting out as much as possible of the code and seeing if you can get something on the page to show.
It could be due to an unclosed quote somewhere in your code, or an unclosed brace. This might cause the echo statement to be viewed as text or in another function, etc.
And, while all errors SHOULD be being reported, I have found that not all errors are actually reported, probably because of ini settings on a shared host that is out of my reach.
Commenting out is not always enough - not sure why not. When this happens, I usually find it to be quickest just to copy the page, and slowly cut and paste sections back in till I find the error, after which I can kick myself for a silly typo.
I had the same problem because I was using:
ob_flush()
did you check your files for closing ?> tags? Or more importantly any whitespace after them...

Categories