Reputation: 83
Im working on a class to make SVN changes through a PHP application. I'm calling svn commands through exec() and trying to throw an exception on error to revert any changes.
Here is the relevant part of the SVN class:
private function svn_exec($cmd) {
$out = array();
$err = 0;
exec($cmd, $out, $err);
if ($err) {
throw new SVNException("$cmd exited with a status of $err");
}
}
And the custom Exception, contained in the same file as the SVN class:
class SVNException extends \Exception {
public function __construct($message = null, $code = 0, \Exception $previous = null) {
error_log("SVN Error: " . $message);
parent::__construct("A Subversion error has occurred.", $code, $previous);
}
}
And the calling code in another class:
public function ApplySVNChanges() {
try {
$svn->update();
// Do a bunch more stuff...
$svn->commit();
} catch (\utils\SVNException $se) {
error_log("Exception caught in SVN class."); // <-- Being logged
$svn->revert();
throw $se; // Throw to caller so db changes are rolled back
}
}
SVN Update is throwing an SVNException, before I can move on to why I need to figure out my the application is crashing and not handling the SVNException like it should. According to the error logs the SVNException is being unhandled. The call to $svn->update() is in a try/catch block that should catch SVNExceptions however, so I'm confused as to why it isn't being handled.
PHP Fatal error: Uncaught exception 'utils\SVNException' with message 'A Subversion error has occurred.' in /path/SVNFunctions.php:114\nStack trace:\n#0 /path/SVNFunctions.php(73): utils\SVNFunctions->svn_exec('svn update --us...')\n#1 /path/CallingClass.php(120)
Update: After adding messages to the catch blocks to log when exceptions are being caught, I found that the SVN exception is being caught, but when rethrown the method above it that calls it isn't catching it. The original try catch
block is part of a method that gets called by another method with its own block to revert SVN and db changes to keep them synced.
try {
ApplySVNChanges(); // Throws SVNException
// Database related changes...
$db-commit();
} catch (Exception $e) {
error_log('Caught Exception in main caller.'); // <-- NOT being logged
if($e instanceof \core\DatabaseException OR $e instanceof \utils\SVNException) {
$db->rollback();
} else {
throw $e;
}
}
According to the error logs the update command is throwing the exception. It is being caught by the first catch, revert is called, and the catch
in the calling method for Database and SVN Exceptions isn't catching it.
Upvotes: 3
Views: 746
Reputation: 83
Found the problem. The try-catch block containing the calls to the other methods that throw SVNException:
catch (Exception $e) {
if($e instanceof \core\DatabaseException OR $e instanceof \utils\SVNException) {
$db->rollback();
} else {
throw $e;
}
}
Wasn't actually catching SVNExceptions or DatabaseExceptions. Adding a backslash before Exception fixed the problem:
catch (\Exception $e) {
The SVNExceptions are being handled as intended.
Edit: For the curious, this answer to another question: https://stackoverflow.com/a/12170579/5530617 actually solved the issue that was causing $svn->update() to throw an exception to begin with by adding the --config-dir
option to the shell command.
Upvotes: 2
Reputation: 987
How are you doing svn->revert()
? could it be that svn->revert()
is calling svn->exec
or doing somehting else that makes the exception rethrow?
I'm simply guessing, but if revert could fail and throw SVNException I think that's whats happening here..
You could test by simply changing the catch part, with something like echo "test"; exit;
instead of $svn->revert();
UPDATE:
After your update, you've added a typo, change $throw se
to throw $se
,
public function ApplySVNChanges() {
try {
$svn->update();
// Do a bunch more stuff...
$svn->commit();
} catch (\utils\SVNException $se) {
error_log("Exception caught in SVN class."); // <-- Being logged
$svn->revert();
throw $se; // Throw to caller so db changes are rolled back
}
}
Upvotes: 2