C Extension Cleanup

I’m writting a wrapper for a C library[1] and need to perform some
clean-up when the Ruby process exists. In my Init function, I create a
C global variable that needs to be explicitly freed after the garbage
collector has finished cleaning up all Ruby objects. How should this be
done?

-Justin

On Oct 16, 2006, at 12:01 AM, Justin B. wrote:

I’m writting a wrapper for a C library[1] and need to perform some
clean-up when the Ruby process exists. In my Init function, I
create a
C global variable that needs to be explicitly freed after the garbage
collector has finished cleaning up all Ruby objects. How should
this be
done?

As far as I understand, there is not such handler. However, You may
register
global object, that will be destroyed when ruby exits. This global
object
will start your cleaner.

Max L. wrote:

As far as I understand, there is not such handler. However, You may
register
global object, that will be destroyed when ruby exits. This global
object
will start your cleaner.

The problem is, it’s not a Ruby object and I need to run some an outside
function to facilitate the clean-up. I tried creating and wrapping the
object in an anonymous class, registering the class and the instance as
global but I had segmentation fault issues (it was being freed early for
some reason.)

On Oct 15, 2006, at 1:01 PM, Justin B. wrote:

I’m writting a wrapper for a C library[1] and need to perform some
clean-up when the Ruby process exists. In my Init function, I
create a
C global variable that needs to be explicitly freed after the garbage
collector has finished cleaning up all Ruby objects. How should
this be
done?

Chapter 21 of the Pickaxe (2nd ed) is what you want. It covers this
topic fairly well.

Justin B. wrote:

 rb_global_variable(world_holder);

}

but still get segmentation faults.

Your free_my_global_object() function should be called at exit. Is it?

Ryan D. wrote:

Chapter 21 of the Pickaxe (2nd ed) is what you want. It covers this
topic fairly well.

I’m not exposing a Ruby object though. Also, the order in which the
objects are freed when the interpreter process exits matters: if my
world object is freed before the instances, there will be a segmentation
fault. The order in which circularly referenced objects are freed at
exit seems to be undefined, so maintaining a reference for every object
won’t work well.

As I said before, I tried something along the lines of:

my_global_object *world;
VALUE world_holder;

void Init_extension()
{
world = create_world();
world_holder = Data_Wrap_Struct(rb_cObject, 0,
free_my_global_object, world);
rb_global_variable(world_holder);
}

but still get segmentation faults.

Joel VanderWerf wrote:

Your free_my_global_object() function should be called at exit. Is it?

It is. The problem is, it’s called before freeing other wrapped
datastructures whose free funtions depend on the existance of the world
object. This results in as segmentation fault or a bus error.

I need to ensure that my free_my_global_object function isn’t called
until all of my other objects have been freed.

On Mon, 16 Oct 2006, Justin B. wrote:

It is. The problem is, it’s called before freeing other wrapped
datastructures whose free funtions depend on the existance of the world
object.

then those objects should have a reference to it - to prevent it from
being
freed by the gc…

I need to ensure that my free_my_global_object function isn’t called until
all of my other objects have been freed.

it just seems like you are delcaring normal ruby gc semantics - ‘free it
only
when no references exist’ - so the easiest thing might to to wrap it,
set a
class variable to that value, and have all your objects hold references
to it.

-a

Hi,

At Mon, 16 Oct 2006 07:17:12 +0900,
Justin B. wrote in [ruby-talk:219893]:

 rb_global_variable(world_holder);
   rb_global_variable(&world_holder);

but still get segmentation faults.

Naturally.

Nobuyoshi N. wrote:

rb_global_variable(&world_holder);

It still faults with a Bus Error, except this time it’ll wait until
finish running my test suite instead of faulting at unrelated points
half-way through.