6

I was challenged how to break or end execution of a parent function without modifying the code of the parent, using PHP

I cannot figure out any solution, other than die(); in the child, which would end all execution, and so anything after the parent function call would end. Any ideas?

code example:

function victim() {
    echo "I should be run";
    killer();
    echo "I should not";
}
function killer() {
    //code to break parent here
}
victim();
echo "This should still run";
  • http://php.net/register_tick_function -- tick functions are obscure, probably performance nightmares, and somewhat poorly documented. But they allow you to effectively execute a function of your choosing every n statements. Meaning your tick function could execute in the middle of any other function's execution. – Frank Farmer Jul 01 '10 at 01:36
  • @Frank I would be interested how that could be turned into a solution for this "problem". By all means, somebody post an answer, please! :) – deceze Jul 01 '10 at 01:52
  • For the record, [runkit_function_redefine()](http://us3.php.net/manual/en/function.runkit-function-redefine.php) doesn't like it when you redefine a currently-running function. :) – Annika Backstrom Jul 01 '10 at 11:06

2 Answers2

7
function victim() {
    echo "I should be run";
    killer();
    echo "I should not";
}
function killer() {
    throw new Exception('Die!');
}

try {
    victim();
} catch (Exception $e) {
    // note that catch blocks shouldn't be empty :)
}
echo "This should still run";
deceze
  • 510,633
  • 85
  • 743
  • 889
  • ok thanks, i thought for some reason the exception would return to victim();. is there any way to do such a thing without the try block? – Franklyn Tackitt Jul 01 '10 at 01:08
  • @Fran No (well, maybe internally it's possible, but it would be very hacky). You could handle the exception inside victim, wrap victim in an other function that would handle the exception or just return a boolean value in killer that says whether the execution should continue and have victim respect that. – Artefacto Jul 01 '10 at 01:11
  • Thats what i figured, i was more curious that anything. thanks guys! – Franklyn Tackitt Jul 01 '10 at 01:12
  • If an exception is thrown, the code execution moves to the first applicable `catch` block up the stack. If there is non, the default exception handler will catch it and halt the whole script. So, when using exceptions, you need a `catch` block. I couldn't think of another way to solve this "puzzle" right now. – deceze Jul 01 '10 at 01:12
1

Note that Exceptions are not going to work in the following scenario:

function victim() {
  echo "this runs";
  try {
    killer();
  }
  catch(Exception $sudden_death) {
    echo "still alive";
  }
  echo "and this runs just fine, too";
}

function killer() { throw new Exception("This is not going to work!"); }

victim();

You would need something else, the only thing more robust would be something like installing your own error handler, ensure all errors are reported to the error handler and ensure errors are not converted to exceptions; then trigger an error and have your error handler kill the script when done. This way you can execute code outside of the context of killer()/victim() and prevent victim() from completing normally (only if you do kill the script as part of your error handler).

user268396
  • 11,576
  • 2
  • 31
  • 26