C Extension Shutdown GC vs Free Functions Called

It was my assumption that during shutdown the objects would be freed
leaf objects first, and a mark and sweep like approach. It seems however
that Ruby just walks an object table and frees each in entry order.

For native (C/C++) object graphs this can lead to out of order
deallocations. In my particular case this leads to a SEGV.

I was hoping to avoid pulling in Boost to add reference counting, was
hoping that the GC integration with Mark and Sweep would help, but it
would appear it does not?

Would someone please comment on approaches to systematically free C++
objects (in a Ruby C Extension) in the proper order?

Am I left solely with a reference counting approach?

Thanks,

Bob

···

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

Robert Buck wrote in post #1085583:

It was my assumption that during shutdown the objects would be freed
leaf objects first, and a mark and sweep like approach. It seems however
that Ruby just walks an object table and frees each in entry order.

For native (C/C++) object graphs this can lead to out of order
deallocations. In my particular case this leads to a SEGV.

Hi,

If you have to free the objects in certain order, in C/C++ you have to
record only one Ruby object which is the root, then you create pointers
to all other leaf (non-root) Ruby objects; in the free function
pointers, you set all the leaf (non-root) Ruby objects as NULL.
Hopefully you don't create too many temporary leaf (non-root) objects,
as all we be freed only when root is freed.

Regards,

Bill

···

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

Unsure if this really applies. Could you restate? I am not quite
following you.

Let me provide additional details...

The use case is a database driver where a connection begets prepared
statement objects which begets result set objects which begets column
info objects.

At each layer of objects we wrap its corresponding struct using
Data_Wrap_Struct as each object has functions (written in C) exposed to
Ruby that may operate on it.

I did set this up so that the child objects have a VALUE reference to
its parent.

But it certainly is the case that Ruby does not do one last Mark and
Sweep before it shuts down after removing all entries from the object
table. Instead it appears as though Ruby simply does a bulk delete
willy-nilly with no concerns about deletion order (which minimally
should occur in at least reverse order of allocation, again which Ruby
does not do).

Admin Tensor wrote in post #1085669:

···

Robert Buck wrote in post #1085583:

It was my assumption that during shutdown the objects would be freed
leaf objects first, and a mark and sweep like approach. It seems however
that Ruby just walks an object table and frees each in entry order.

For native (C/C++) object graphs this can lead to out of order
deallocations. In my particular case this leads to a SEGV.

Hi,

If you have to free the objects in certain order, in C/C++ you have to
record only one Ruby object which is the root, then you create pointers
to all other leaf (non-root) Ruby objects; in the free function
pointers, you set all the leaf (non-root) Ruby objects as NULL.
Hopefully you don't create too many temporary leaf (non-root) objects,
as all we be freed only when root is freed.

Regards,

Bill

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

For what its worth, I just tried hooking into the at exit hook at the
C/C++ side. But that gets called AFTER Ruby bulk dumps/deletes all
objects out of order. I was hoping to have this intercepted prior to
global object deletion so that I could put the driver into a special
mode, the don't free anything mode (since memory will be cleaned up
anyways when the proc terminates).

···

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

Robert Buck wrote in post #1085679:

For what its worth, I just tried hooking into the at exit hook at the
C/C++ side. But that gets called AFTER Ruby bulk dumps/deletes all
objects out of order. I was hoping to have this intercepted prior to
global object deletion so that I could put the driver into a special
mode, the don't free anything mode (since memory will be cleaned up
anyways when the proc terminates).

Hi,

I am sorry that I don't know the precise situation. If you just want
memory to be cleaned up automatically when the proc terminates, then in
Data_Wrap_Struct(klass, mark, free, ptr), just set NULL for the "free"
pointer. But of course this assumes that the SEGV occurs because of the
C-related code, not Ruby-related code, and hopefully the database also
does not require special handling during automatic termination.

Regards,

Bill

···

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