From: Renee Date: 2012-11-25T01:14:15+09:00 Subject: Re: C Extension: Why would VALUE state appear differently during shutdown than immediately before it I live for the day 80% of these posts don't sound like Greek to me. Being pretty new to all of this though I am loving the little 'peek inside' Ok, carry on :) Sent from my iPhone On Nov 24, 2012, at 10:55 AM, Robert Buck wrote: > For the record, if anyone else tries to write a database driver, or any > C extension that has a graph of objects that have deallocation order > dependencies... > > If you are integrating with mark and sweep, and provide free hooks for > your objects, be aware that at shutdown Ruby drops objects from its > object table in allocation order (table order). This means that once it > has called your free-hooks (defined in your calls to Data_Wrap_Struct), > afterwards ever after YOU CANNOT / MUST NOT, ***EVER*** call > Data_Get_Struct on a VALUE that has been visited/dropped from the Ruby > object table. Ruby will SEGV with a very hard to diagnose issue. > > Your C structs should probably do something like this: > > struct hierarchical_handle > { > // the hook to the real C/C++ free code, never accessed > // directly by Ruby GC, only via ref count decr routines > RUBY_DATA_FUNC free_func; > > // increment this to 1 on allocation, children inc count > // only free-hooks decr counts; in fact, your free-hooks > // could simply be atomic_dec(handle*) > rb_atomic_t atomic; > > // used by ref counting routines to pin C/C++ objects > // in memory till the last one drops its reference > nuodb_handle * parent_handle; > > // used to pin parents in memory via rb_gc_mark > VALUE parent; > }; > > Like me, just steal atomic.[c|h] from Ruby. But N.B. There is a major > bug in them, somebody in the Ruby camp used the WRONG > GCC_ATOMIC_BUILTINS !@!! > > Somebody ought to fix atomic.h, its screwed up badly. > > Robert Buck wrote in post #1086203: >> I have a graph of objects in a C extension, and as such I maintain >> reference counts from children to parents as deallocations are order >> dependent (see struct definition below). >> >> While I run my program the reference counts match up, but when the >> program exits, when ruby dumps its entire object table calling free on >> every VALUE the parent's free functions are called before the children >> as the parents were allocated first and they appear in the ruby object >> table first (this was the whole reason for adding reference counting, >> because otherwise order dependent deallocations in C code causes a >> SEGV). >> >> Anyways, before shutdown here are my ref counts: >> >> [REFERENCE COUNT][O INCR] (child @ 00007fd6d0ddd5c0): 1 (parent @ >> 00007fd6d2538460): 2 >> >> n.b. 2 refs >> >> And after shutdown the ref counts are "magically" different: >> >> [REFERENCE COUNT][I DECR] (child @ 00007fd6d2538460): 1 (parent @ >> 0000000000000000): -10 >> >> n.b. -10 is just a sentinel marker, ignore that >> n.b. 1 refs though does not match 2 above >> >> The latter trace is for the root object, hence no parent. But notice the >> root object's reference count of 1. Take a look at its reference count >> before program termination, 2. >> >> This is saying that I have a case of memory corruption on my part, >> memory corruption on ruby's part, or my understanding of how to set up >> graphs of interrelated objects in C extensions is seriously flawed. >> >> Regarding the last option, all I am doing is maintaining a struct of: >> >> struct handle >> { >> RUBY_DATA_FUNC free_func; >> rb_atomic_t atomic; >> VALUE parent; >> }; >> >> Would someone have an idea of how to approach this, what could possibly >> be going on? I have been at this for three days now and I don't see any >> bug on my part. >> >> Bob > > -- > Posted via http://www.ruby-forum.com/. >