GC on two C extension objects

I am running into a problem with to C extension objects and I’m not sure
what I’m missing. I put together a simple example illustrating the point
here:

https://github.com/linterra/ruby-c-ext-gc

Basically one C extension class (child) references another (parent). To
keep parent from being GC’d before the child referencing it, I assign a
reference in the child using rb_ivar_set(). Additionally, I also add a
mark
function in the child to mark the parent.

Still, when GC runs, the parent still gets cleaned up first and the
child
GC segfaults because it references the GC’d parent. I can see that the
child’s mark function is being called.

So I am not sure what I am missing. What should I be doing to make sure
the
child keeps a valid reference to the parent to ensure that it (parent)
is
not GC’d before child?

I have tested this on Ruby 1.9.3 latest. 1.9.1 also exhibits the same
behavior. 1.8.6 It does not exhibit this behavior, but apparently
because
it does not GC the child at all.

Any help would be greatly appreciated.

Mike

Is the GC being run when the app exits? That can collect object “willy
nilly” or so I’m told.

Yes – that’s where the problem first cropped up.

Mike Owens писал 13.04.2012 21:02:

keep parent from being GC’d before the child referencing it, I assign

Mike

This is the intended behavior. Objects are not sweeped in an order
related to
their reference contents; instead, the mark phase just searches for
islands
of unused objects and sweep phase destroys these islands. Why does it
work
this way? Easy. First, there is no sensible sweep order in case of
circular
reference. Second, GC should be as fast as possible, and ensuring a
particular
order of sweeping would incur significant computational cost.

You should keep all your data in a single “pivot” object and only
return thin
references to that data in accessors. Think of a DOM document and a
node list.

Okay, thanks. I had not thought of cyclic dependencies.