From: Tilman Sauerbeck Date: 2004-07-31T03:37:22+09:00 Subject: Re: C ext: GC claiming objects early Charles Mills [2004-07-30 19:31]: > > On Jul 30, 2004, at 7:06 AM, Tilman Sauerbeck wrote: > > >ts [2004-07-30 15:43]: > >>>>>>>"T" == Tilman Sauerbeck writes: > >> > >>T> "some_meth" will instantiate a new "Result" object. Using this > >>Result > >>T> object, the caller can wait for the function to succeed, he can > >>register > >>T> callbacks etc. > >> > >> Well it's best if you post the *real* C code : it's easy to > >>understand > >> than this strange language, called english. > > > >Heh :) > > > >[C code] > You should show us c_mark and c_free static void c_mark (RbResult *res) { if (!NIL_P (res->parent)) rb_gc_mark (res->parent); if (!NIL_P (res->callback)) rb_gc_mark (res->callback); } static void c_free (RbResult *res) { if (res->real) { xmmsc_result_unref (res->real); res->real = NULL; } res->parent = Qnil; free (res); } > In extreme situations the above code it dangerous, here is a safer > version: > > VALUE self; > RbResult *rbres; > > if (!res) > return Qnil; > > rbres = ALLOC(RbRecsult); > rbres->real = res; > rbres->parent = parent; > rbres->callback = Qnil; > self = Data_Wrap_Struct (cResult, c_mark, c_free, rbres); > You mean the memset() call of Data_Make_Struct is dangerous? I kind of doubt memset is causing problems here, but I'll try it anyway :) > > rb_obj_call_init (rbres->self, 0, NULL); > > > > return self; > Where did rbres->self come from? Doesn't look like you initialized it. > You need to pass a valid Ruby object to rb_obj_call_init(), perhaps > you intended: > > return rb_obj_call_init(self, 0, 0); /* returns self */ > Yeah, it was a typo which didn't occur in my original code *hides* > > > >'parent' is the Ruby object that the object marks in c_mark > > > >This is the "notifier" method of the Result object and the callback > >used > >to call the given block: > > > >static void on_signal (xmmsc_result_t *res2, void *data) > >{ > > /* call the block and create a new Result object from res2, too */ > > rb_funcall ((VALUE) data, rb_intern ("call"), 1, > > TO_XMMS_CLIENT_RESULT (Qnil, res2)); > >} > > > >static VALUE c_notifier_set (VALUE self) > >{ > > GET_OBJ (self, RbResult, res); > > > > if (!rb_block_given_p ()) > > return Qnil; > > > > res->callback = rb_block_proc (); > > xmmsc_result_notifier_set (res->real, on_signal, (void *) > >res->callback); > This could be your problem. We encountered a similar problem last night > with the Rendezvous Ruby wrappers. > rb_block_proc() creates a ruby object. > your registering on_signal as your event handler, and it looks like > what ever library you are using (you should supply more code here) will > the pass the void* to the call back for you. You need to show c_mark() > so it is clear that your marking everything. Yes, the library does pass res->callback as the data pointer to on_signal. You are right, I should have commented on it, but it's such a common technique in C I thought I wouldn't have to explain it :p -- Regards, Tilman