Catch an exception in a shutdown function-Collection of common programming errors
I’m working on some PHP code that needs to obtain a database resource, mark it as locked for the duration of its run and mark it as not locked when done. The lock is obtained at startup by updating a value in the table, and I’ve registered a shutdown function to release the lock when the script terminates for any reason.
The problem I’m having is that the connection to the server (a Microsoft SQL database server) doesn’t appear to be very reliable in the live environment, and that seems to be the usual reason for abnormal script termination. Obviously I can’t unlock the database resource when I’m not connected but I at least want to be able to handle the failure to do that cleanly.
The following is a heavily cut down version of the main script.
try {
echo "Connecting to server...\n";
$obj_adaptor = get_remote_db ();
echo "Beginning sync...\n";
if (FALSE != ($bol_locked = $obj_adaptor -> lock_server_db ())) {
// Do work here
} else {
throw new RuntimeException ("Failed to obtain remote database lock!");
}
} catch (Exception $obj_ex) {
echo "Operation failed with an exception!\n\n";
echo "Details: \n";
echo $obj_ex -> getMessage () . PHP_EOL;
echo $obj_ex -> getTraceAsString () . PHP_EOL;
}
My shutdown function looks like this:
$arr_shutdown_func = function () {
global $bol_locked, $obj_adaptor;
if ($bol_locked) {
echo "Releasing lock...\n";
try {
echo $obj_adaptor -> unlock_server_db ()?
"Done\n":
"Failed to unlock database! Use force_remote_db_unlock script to force a database unlock\n";
} catch (PDOException $obj_ex) {
echo "Failed to unlock database! Use force_remote_db_unlock script to force a database unlock\n";
}
} else {
echo "No lock to release\n";
}
};
// Set up ctrl-c listener
if (function_exists ('pcntl_signal')) {
pcntl_signal (SIGINT, $arr_shutdown_func);
pcntl_signal (SIGTERM, $arr_shutdown_func);
// Register shutdown functions
register_shutdown_function ($arr_shutdown_func);
set_exception_handler ($arr_shutdown_func);
I was expecting in the event of the connection being lost for the script to attempt to release the database lock but failing, and echoing out the message about not being able to release the lock.
However, what I actually get is:
PHP Fatal error: Uncaught exception ‘Zend_Db_Statement_Exception’ with message ‘SQLSTATE[HY000]: General error: 20047 DBPROCESS is dead or not enabled [20047] (severity 1) [(null)]’ in Zend/Db/Statement/Pdo.php:238
I’ve tried to find a definitive answer on whether or not it’s possible to catch exceptions in a shutdown function but haven’t had much luck so far so I’m still looking. However, if it’s possible to deal with exceptions in a shutdown function I’d appreciate knowing what’s wrong with the approach I’m applying.
-
I’ve just tested this out with a simple code and I don’t get disconnected before shutdown function.
What version of PHP are you using?
PHP 5.5.3 (cli) (built: Aug 23 2013 08:41:45) Copyright (c) 1997-2013 The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies