Help with destructor order?

[email protected] (Kristina Chodorow)
Newsgroups php.pecl.dev
Message-ID <[email protected]>
I maintain the mongo PECL extension and I'm having a problem with my
destructors.

I have two classes, each of which is tied to a struct (i.e., I define the
create_object field for the class entry and put the struct in the
zend_object_value).  So, the classes look something like:

ConnectionClass
struct {
    zend_object std;
    /* other fields */
} connection;

DBClass
struct {
    zend_object std;
    zval *connection;
    /* other fields */
} db;

When I create an instance of DBClass, I:

   1. Pass it an instance of ConnectionClass
   2. Set the db struct's connection field to the ConnectionClass instance
   3. Increment the ConnectionClass instance's reference count

This works great in most cases, but if I create a local instance of
ConnectionClass and a static instance of DBClass, the order of destructors
gets messed up:

<?php

class Foo {
    static $db;

    public function f() {
        $c = new ConnectionClass();
        Foo::$db = new DBClass($c);
    }
}

$f = new Foo();
$f->f();

?>

ConnectionClass's struct destructor method is called before DBClass's,
despite having a higher reference count.  DBClass's struct destructor calls
zval_ptr_dtor(&db->connection), but db->connection has already had its
struct freed, which causes segfaults.

I don't really know how PHP handles destroying static vs. non-static
variables, so I'm not sure what's causing this, but is there any way to let
PHP know that ConnectionClass instances should hang around at least as long
as the DBClass instance that contains them?  "Promote" them to static
variables somehow?  I thought reference counting would do it, but obviously
not.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.