From: SourceForge.net <no...@so...> - 2009-03-05 07:00:35
|
Bugs item #2034216, was opened at 2008-07-31 12:37 Message generated for change (Comment added) made by cfis You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101645&aid=2034216&group_id=1645 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: ruby Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: Alex (bro_ken_toy) Assigned to: Gonzalo Garramuno (gga73) Summary: [ruby] generated tracking code errors with Ruby 1.8.7 / 1.9 Initial Comment: SWIG's generated tracking code is not compatible with the latest ruby versions : 1.8.7 and 1.9 Specifically, during ruby's garbage collection phase, the function SWIG_RubyRemoveTracking may be called, which in turn calls SWIG_RubyPtrToReference. This converts a void* (ptr to the C++ object) to a ruby numeric corresponding to the pointer address, which is then used as a ruby hash key. The pointer address may convert into a Ruby BigNum, which is a new object allocation. As of Ruby 1.8.7 / Ruby 1.9 object allocation during GC phase is a bug and will crash out with an error message. For the time being we (wxRuby) have worked round this be re-implementing the tracking code using a HashMap class from wxWidgets, but this isn't a general solution. This problem will affect any SWIG/Ruby project that uses the tracking code. ---------------------------------------------------------------------- >Comment By: cfis (cfis) Date: 2009-03-05 00:00 Message: I think the best solution here is to use ruby's C level hash table - st_table. When I originally implemented this code I didn't realize that existed. That would eliminate the call back into Ruby.... ---------------------------------------------------------------------- Comment By: Tobias Grimm (tiber) Date: 2009-02-10 19:37 Message: Just stumbled across this bug as well. I borrowed the wxRuby workaround (thanks guys!) with a std::map, but this should really be fixed in SWIG. ---------------------------------------------------------------------- Comment By: Tobias Grimm (tiber) Date: 2009-02-10 19:34 Message: Just stumbled across this bug as well. I borrowed the wxRuby workaround (thanks guys!) with a std::map, but this should really be fixed in SWIG. ---------------------------------------------------------------------- Comment By: Kevin Burge (kcburge) Date: 2008-10-22 20:30 Message: If you look at the Ruby repository when the "object allocation during garbage collection phase" patch was applied: svn diff -r17139:17140 http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8_6 You'll see they had the same hash-tracking problem for DL. I just modified my own swig generated code with the following patch, and it seems to have resolved the Fixnum problem for the tracking swig object pointers: diff --git a/xtt/swig/ruby/xtt.c b/xtt/swig/ruby/xtt.c index f64e987..ded5f89 100644 --- a/xtt/swig/ruby/xtt.c +++ b/xtt/swig/ruby/xtt.c @@ -802,6 +802,7 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { #include <ruby.h> +#include <st.h> /* Remove global macros defined in Ruby's win32.h */ #ifdef write @@ -1095,7 +1096,7 @@ extern "C" { /* Global Ruby hash table to store Trackings from C/C++ structs to Ruby Objects. */ -static VALUE swig_ruby_trackings = Qnil; +static st_table* swig_ruby_trackings; /* Global variable that stores a reference to the ruby hash table delete function. */ @@ -1112,17 +1113,14 @@ SWIGRUNTIME void SWIG_RubyInitializeTrackings(void) { This is done to allow multiple DSOs to share the same tracking table. */ - ID trackings_id = rb_intern( "@__trackings__" ); VALUE verbose = rb_gv_get("VERBOSE"); rb_gv_set("VERBOSE", Qfalse); - swig_ruby_trackings = rb_ivar_get( _mSWIG, trackings_id ); rb_gv_set("VERBOSE", verbose); /* No, it hasn't. Create one ourselves */ - if ( swig_ruby_trackings == Qnil ) + if ( !swig_ruby_trackings ) { - swig_ruby_trackings = rb_hash_new(); - rb_ivar_set( _mSWIG, trackings_id, swig_ruby_trackings ); + swig_ruby_trackings = st_init_numtable(); } /* Now store a reference to the hash table delete function @@ -1130,16 +1128,6 @@ SWIGRUNTIME void SWIG_RubyInitializeTrackings(void) { swig_ruby_hash_delete = rb_intern("delete"); } -/* Get a Ruby number to reference a pointer */ -SWIGRUNTIME VALUE SWIG_RubyPtrToReference(void* ptr) { - /* We cast the pointer to an unsigned long - and then store a reference to it using - a Ruby number object. */ - - /* Convert the pointer to a Ruby number */ - return SWIG2NUM(ptr); -} - /* Get a Ruby number to reference an object */ SWIGRUNTIME VALUE SWIG_RubyObjectToReference(VALUE object) { /* We cast the object to an unsigned long @@ -1168,23 +1156,21 @@ SWIGRUNTIME void SWIG_RubyAddTracking(void* ptr, VALUE object) { instead we typecast it as a unsigned long and convert it to a Ruby number object.*/ - /* Get a reference to the pointer as a Ruby number */ - VALUE key = SWIG_RubyPtrToReference(ptr); - /* Get a reference to the Ruby object as a Ruby number */ VALUE value = SWIG_RubyObjectToReference(object); /* Store the mapping to the global hash table. */ - rb_hash_aset(swig_ruby_trackings, key, value); + st_insert(swig_ruby_trackings, (st_data_t)ptr, value); } /* Get the Ruby object that owns the specified C/C++ struct */ SWIGRUNTIME VALUE SWIG_RubyInstanceFor(void* ptr) { - /* Get a reference to the pointer as a Ruby number */ - VALUE key = SWIG_RubyPtrToReference(ptr); - /* Now lookup the value stored in the global hash table */ - VALUE value = rb_hash_aref(swig_ruby_trackings, key); + VALUE value; + + if (!st_lookup(swig_ruby_trackings, (st_data_t)ptr, &value)) { + return Qnil; + } if (value == Qnil) { /* No object exists - return nil. */ @@ -1201,12 +1187,9 @@ SWIGRUNTIME VALUE SWIG_RubyInstanceFor(void* ptr) { since the same memory address may be reused later to create a new object. */ SWIGRUNTIME void SWIG_RubyRemoveTracking(void* ptr) { - /* Get a reference to the pointer as a Ruby number */ - VALUE key = SWIG_RubyPtrToReference(ptr); - /* Delete the object from the hash table by calling Ruby's do this we need to call the Hash.delete method.*/ - rb_funcall(swig_ruby_trackings, swig_ruby_hash_delete, 1, key); + st_delete(swig_ruby_trackings, (st_data_t *)&ptr, NULL); } /* This is a helper method that unlinks a Ruby object from its @@ -8930,6 +8913,7 @@ SWIGEXPORT void Init_xtt_api(void) { /* MANUAL */ SWIG_define_class(swig_module.types[i]); } + swig_ruby_trackings = NULL; SWIG_RubyInitializeTrackings(); rb_define_const(mCore, "XTT_EI_OKAY", SWIG_From_int((int)(XTT_EI_OKAY))); rb_define_const(mCore, "XTT_EI_ERR_in", SWIG_From_int((int)(XTT_EI_ERR_in))); ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101645&aid=2034216&group_id=1645 |