From: "Iñaki Baz Castillo" Date: 2011-02-07T06:17:03+09:00 Subject: Re: C extension: How to check if a VALUE is still alive (not being GC'ed)? 2011/2/6 Tony Arcieri : >> The problem is that the VALUE could be GC'ed (or being marked for so) >> if the programmer assigns it to "nil" before the callback is executed, >> so we get a coredump. >> >> So when the callback is executed I need to check that the given VALUE >> is still alive (not GC'ed neither marked for being GC'ed). How can I >> inspect that? (I mean in C). > > > How is rb_gc_mark() insufficient here? Marking prevents objects from being > GCed... you seem to be suggesting it's the other way around. Sorry, I was wrong about the meaning of "marking an object". > If you mark all VALUEs your C extension is internally referencing in your C > extension's "mark" function it will prevent them from being garbage > collected. But this is not my case. My case is as follows (an example code): ------------------------------------------------------------------------------------- domain = ARGV[0] module UdnsWatcher def initialize(resolver) @resolver = resolver end def notify_readable @resolver.ioevent end end EM.run do resolver = EM::Udns::Resolver.new EM.watch resolver.fd, UdnsWatcher, resolver do |conn| conn.notify_readable = true end query = EM::Udns::Query.new query.submit_A resolver, domain query.callback do |result| puts "DEFERRABLE CALLBACK: result = #{result.inspect}" end end ------------------------------------------------------------------------------------- - "Resolver" class is my C extension which wraps a C struct 'dns_context', no more Ruby objects for now. - "Query" class is pure Ruby and includes EM::Deferrable (it has nothing else). - "query.submit_A resolver, domain" invokes a function of udns C library: VALUE Query_submit_query_A(VALUE self, VALUE context, VALUE str) { struct dns_ctx *dns_context = NULL; char *domain; Data_Get_Struct(context, struct dns_ctx, dns_context); domain = StringValueCStr(str); dns_submit_a4(dns_context, domain, 0, dns_res_A_cb, (void*)self); [...] } As you can see "self" is passed as argument to dns_submit_a4(). This is because when the DNS response arrives, a callback "dns_res_A_cb()" function will be called, and that function contains as argument the same (void*)self so I can know which Query instance the response belongs to, and can invoke "set_deferred_status" by using rb_funcall(). But in my above Ruby code I don't store "query" in a hash or array, so it could be GC'ed before the DNS response arrives, so when the callback is called I'd get a coredump. I don't want to store "query" in a Hash or Array since it requires inserting and deleting it (so wasted time), I just want "query" not to be GC'ed until udns callback function is executed. So, if I include rb_gc_mark(self) in Query_submit_query_A() function, would it prevent "query" from being GC'ed? But in this case, how to unmark it so it can be GC'ed after query completes? wouldn't leak if not? (note that Resolver instance lives forever. Thanks a lot. -- Iñaki Baz Castillo