As much as I love using Drupal, every once in a while something goes horribly, horribly wrong. Mind you, in most cases, I may have had a hand in the error (updated the wrong module, forgot a file or two, etc...) but the end result is the same; the dreaded WSOD (White Screen Of Death). These occur when PHP has some kind of error while processing your request. The problem with this is the user, unless they're technically inclined, has no idea why all they see is a big blank white screen (I'm assuming you've disabled the output of errors to the page in production. If you haven't, what are you waiting for!). Not only that, they'll just keep refreshing the page and potentially adding to your problems by having half executed PHP code running a muck on your data.
Wouldn't it be nice to gracefully display an error message or something to the user so they have a clue as to what's going on. Even better, what about having the error message send off a message to your system administrators letting them know of the error? Sounds nice doesn't it. In most cases, this is possible to add right in the code of your site. If you add the proper try/catch cases, you should be able to avoid most errors and display a nice message to the user and log the error. The real issue is with PHP Fatal errors. Those buggers kill any and all PHP code from executing after the error occurs. PHP just stops right then and there. You'll get some info in your error_log files (or at least you should, check your php.ini settings or your vhost configuration for log file locations). But in the case of PHP Fatal errors, since your code just stops, all those try/catch blocks with the on screen messages, emails to system administrators, everything just stops. Nothing gets displayed and no message sent.
Seems hopeless. Well it's not, thanks to a lovely little function in PHP called register_shutdown_function. This function allows you to set any function to run once PHP shutsdown. Either when it's done processing your request or when an error occurs (even Fatal Errors!) Yup, that's right, we're going to use PHP to save PHP from displaying nothing. Take a moment to think about that... you good? Excellent!
Now the trick to this is to run your call to register_shutdown_function( my_error_handling_function ) before ANYTHING else runs. That way once an error occurs later on in the code, your function has been registered and will be called. Now with Drupal, this does mean you'll have to hack core (AAAaaahhh!!!) I know, I KNOW! Don't Hack Core! But if you want to be able to catch your fatal errors, you'll have to. You can't count on a module to catch the error since another bit of code before running the module hooks run may cause the fatal error before you can register your function. Luckily, it's a very simple hack. At the top of index.php, just add your error checking code. Should look something similar to this:
function check_shutdown() {
$lasterror = error_get_last();
if ( $lasterror['type'] == E_ERROR ){
// Your error message code...} else {
// Do nothing}}//Register the shutdownfunction register_shutdown_function('check_shutdown');
First you write the function you want to have executed on a fatal error. In this case I called it "check_shutdown". Then in the if statement, I check for the last error produced using the error_get_last() function. This returns the PHP error code for the last error it encountered. Since fatal errors are return code 1 or E_ERROR, I check for that error code. Then I just run whatever I want to run. Could be a simple echo to the page, or a redirect to a standard error page on your server. Obviously, if there was no error, I do nothing.
The great thing about this code is that it can be used in any PHP application, not just Drupal. Just be sure to register the function as the first thing in your code. Also note, you'll want to make your check_shutdown function as independent or self contained as possible. Don't make too many calls to external libraries or even worse, make calls to functions within your application. Remember, this only runs when something goes wrong. You don't necessarily know what went wrong. If you call your PHPMailer function inside Drupal and the error which triggered the shutdown is within that function, this pretty much defeats the purpose of the adding this code to begin with. Try and have a set of libraries or functions that are completely external to your application to do any kind of advanced error handling. This will minimize the chance of triggering the fatal error with your error handling code.
Now, if Drupal misbehaves, you can tell your users that it wasn't their fault and get a notification telling you that something went wrong. Nifty isn't it!


Interesting...
We are looking to disable display_errors, but a WSOD seems worse.
Is there a reason something like this wouldn't be in core?