Use destructor carefully

A couple of days ago I lost half a day of work on a stupid bug in a PHP CLI script. Basically, the script wouldn’t die. Instead it would hang forever, eating all the CPU time. Even explicitly calling die() (or exit(), since they are synonyms) wouldn’t terminate it. Yep, that’s right, die() didn’t work! Until then, I naively believed that die() was some failsafe language construct that would terminate the script not matter what. But as it turned out, it’s not the case…

According to PHP documentation: The destructor will be called even if script execution is stopped using exit(). So destructor’s code will be executed even after die() is called. What happens if a destructor’s code is faulty and gets stuck in an infinite loop ? The script will never end. In my story, I was using an third-party object-oriented library (for AMQP) that did some funky stuff in some objects destructor, and then waited forever for an event on the network… Needless to say, it’s a BAD idea to write that much application logic in a destructor.

So the moral of the story is: (1) die() can fail and (2) use destructor with caution, only write code that will NEVER fail and that is STRICLY necessary like closing connections, closing file handlers and such. Same goes for shutdown functions by the way.

A quick example for the sake of demonstration:

class Evil
{
    public function __destruct()
    {
        while (true);
    }
}

$foo = new Evil();
die();