When a script is in the process of die()ing, you can't count on the order in which __destruct() will be called.
For a script I have been working on, I wanted to do transparent low-level encryption of any outgoing data.  To accomplish this, I used a global singleton class configured like this:
class EncryptedComms
{
    private $C;
    private $objs = array();
    private static $_me;
    
    public static function destroyAfter(&$obj)
    {
        self::getInstance()->objs[] =& $obj;
        /*
            Hopefully by forcing a reference to another object to exist 
            inside this class, the referenced object will need to be destroyed
            before garbage collection can occur on this object.  This will force 
            this object's destruct method to be fired AFTER the destructors of
            all the objects referenced here.
        */
    }
    public function __construct($key)
    {
            $this->C = new SimpleCrypt($key);
            ob_start(array($this,'getBuffer'));
    }
    public static function &getInstance($key=NULL)
    {
        if(!self::$_me && $key)
            self::$_me = new EncryptedComms($key);
        else
            return self::$_me;
    }
    
    public function __destruct()
    {
        ob_end_flush();
    }
    
    public function getBuffer($str)
    {
        return $this->C->encrypt($str);
    }
}
In this example, I tried to register other objects to always be destroyed just before this object.  Like this:
class A
{
public function __construct()
{
     EncryptedComms::destroyAfter($this);
}
}
One would think that the references to the objects contained in the singleton would be destroyed first, but this is not the case.  In fact, this won't work even if you reverse the paradigm and store a reference to EncryptedComms in every object you'd like to be destroyed before it.
In short, when a script die()s, there doesn't seem to be any way to predict the order in which the destructors will fire.