Subject:
[ruby-core:17735] Re: Mark functions not called on exit
From:
Charlie Savage <cfis / savagexi.com>
Date:
Fri, 11 Jul 2008 12:08:02 +0900

To:
ruby-core / ruby-lang.org

Charlie,

From your description below, I believe the fundamental problem might that
the XML document "nodes" in the Node::Set are not Ruby objects.  Because
of this, the garbage collector cannot see that XML::Node:Set has a
dependency
on the parent XML::Document.

It would probably be sufficient to add a pointer to the base of the
parent XML::Document to
the XML::Node::Set being returned by Document#find, even if this object
reference
were not otherwise necessary.   Having the object reference in the
XML::Node::Set
should prevent the garbage collector from freeing an XML::Document
before any XML::Node::Set
referring to it.

Anyway, to fix this "the ruby way", think in terms of a the Ruby object
dependency
graph.  Pointers to anything that is not wrapped up as a Ruby object
will not be
respected as a dependency by the conservative Ruby garbage collector.

Hope this helps...

- brent


> At Thu, 10 Jul 2008 03:40:52 +0900,
> Charlie Savage wrote in [ruby-core:17706]:
>
>> Hmm.  To correctly shut down my extension, I do need to control the
>> order in which the objects are freed.  Is there any way to do this? 
>> And have other people run into this issue (seems like it would be
>> common when freeing resources allocated from a 3rd party library, in
>> this case libxml).
>
>
> Which object is the problem?  Reference count may be useful.


The specifics of this issue are:

1.  Open a XML::Document
2.  Call Document#find which returns an XML::Node::Set
3.  Within libxml, XML::Node::Set maintains a set of pointers to nodes
that are owned by the document.
4.  Ruby process starts exiting
5.  XML::Document is freed
6.  XML::Node::Set is freed - but when it iterates over its list of
nodes to pointers a segmentation fault occurs.

If the order is reversed then there is no problem.  It is possible to
code around this by having Documents maintain pointers to returned
Node::Sets and Node::Sets in turn link back to their parent documents.
But that all seems like a big kludge around the fact that the order of
free calls is random, even though the Node::Set does have an appropriate
mark function.

It seems to me this must be a common thing that should have a built-in
solution.  It would be nice if Ruby could do one mark/sweep/free before
shutting down a process.  Or if that is too much, then a lighter weight
way of saying Object A must be freed before Object B (well, the whole
idea of mark and sweep again).

In this case, I can't see how reference counting would help....

Charlie