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.

···

--
Posted via http://www.ruby-forum.com/.

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

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.

<snip>

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.

···

--
   WBR, Peter Zotov.

Yes -- that's where the problem first cropped up.

···

On Fri, Apr 13, 2012 at 1:00 PM, Roger Pack <lists@ruby-forum.com> wrote:

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

--
Posted via http://www.ruby-forum.com/\.

--
Mike

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

···

On Fri, Apr 13, 2012 at 7:49 PM, Peter Zotov <whitequark@whitequark.org>wrote:

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

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&lt;https://github.com/linterra/ruby-c-ext-gc&gt;

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.

<snip>

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.

--
WBR, Peter Zotov.

--
Mike