From a5592fa14a733edc4c248aadb8543c6cb87113d6 Mon Sep 17 00:00:00 2001 From: Jitka Plesnikova Date: Tue, 15 Sep 2015 08:10:56 +0200 Subject: [PATCH] Fix Ruby tracking code (BZ#1225140) --- swig.spec | 28 ++- ...ix-Ruby-trackings-code-to-use-C-hash.patch | 202 ++++++++++++++++++ swig307-Ruby-trackings-patch-tidy-up.patch | 76 +++++++ swig307-Ruby-trackings-support-for-1.8.patch | 29 +++ 4 files changed, 324 insertions(+), 11 deletions(-) create mode 100644 swig307-Fix-Ruby-trackings-code-to-use-C-hash.patch create mode 100644 swig307-Ruby-trackings-patch-tidy-up.patch create mode 100644 swig307-Ruby-trackings-support-for-1.8.patch diff --git a/swig.spec b/swig.spec index 24b960c..f4c5461 100644 --- a/swig.spec +++ b/swig.spec @@ -5,13 +5,6 @@ %{!?guile:%global guile 1} %{!?lualang:%global lualang 1} -# Ruby segfaults in some tests on fc23 and only on armv7-arch. -#%%ifarch %%{arm} s390 -# Disable Ruby tests for all arches due to BZ#1225140 -%if 0%{?fedora} >= 23 -%{!?rubylang:%global rubylang 0} -%endif # 0%%{?fedora} >= 23 -#%%endif #arch %%{arm} s390 %{!?rubylang:%global rubylang 1} %ifarch aarch64 %{arm} ppc64le ppc %{power64} s390 s390x @@ -40,7 +33,7 @@ Summary: Connects C/C++/Objective C to some high-level programming languages Name: swig Version: 3.0.7 -Release: 4%{?dist} +Release: 5%{?dist} License: GPLv3+ and BSD URL: http://swig.sourceforge.net/ Source0: http://downloads.sourceforge.net/project/swig/swig/swig-%{version}/swig-%{version}.tar.gz @@ -48,6 +41,11 @@ Source0: http://downloads.sourceforge.net/project/swig/swig/swig-%{version}/swig Source1: description.h2m Patch1: swig207-setools.patch +# Ruby patches will be part of SWIG 3.0.8 +Patch2: swig307-Fix-Ruby-trackings-code-to-use-C-hash.patch +Patch3: swig307-Ruby-trackings-patch-tidy-up.patch +Patch4: swig307-Ruby-trackings-support-for-1.8.patch + BuildRequires: perl, python2-devel, pcre-devel BuildRequires: autoconf, automake, gawk, dos2unix BuildRequires: gcc-c++ @@ -111,6 +109,9 @@ This package contains documentation for SWIG and useful examples %setup -q -n swig-%{version} %patch1 -p1 -b .setools +%patch2 -p1 -b .rubyhash +%patch3 -p1 -b .rubytidyup +%patch4 -p1 -b .ruby18 for all in CHANGES README; do iconv -f ISO88591 -t UTF8 < $all > $all.new @@ -201,13 +202,18 @@ ln -fs ../../bin/ccache-swig %{buildroot}%{_libdir}/ccache/swig %{_libdir}/ccache %{_mandir}/man1/ccache-swig.1* %{_mandir}/man1/swig.1* -%doc ANNOUNCE CHANGES CHANGES.current LICENSE LICENSE-GPL -%doc LICENSE-UNIVERSITIES COPYRIGHT README TODO +%license LICENSE LICENSE-GPL LICENSE-UNIVERSITIES +%doc ANNOUNCE CHANGES CHANGES.current +%doc COPYRIGHT README TODO %files doc -%doc Doc Examples LICENSE LICENSE-GPL LICENSE-UNIVERSITIES COPYRIGHT +%license LICENSE LICENSE-GPL LICENSE-UNIVERSITIES +%doc Doc Examples COPYRIGHT %changelog +* Mon Sep 14 2015 Jitka Plesnikova - 3.0.7-5 +- Fix Ruby tracking code (BZ#1225140) + * Tue Sep 01 2015 Jitka Plesnikova - 3.0.7-4 - Disable Ruby tests diff --git a/swig307-Fix-Ruby-trackings-code-to-use-C-hash.patch b/swig307-Fix-Ruby-trackings-code-to-use-C-hash.patch new file mode 100644 index 0000000..360bef6 --- /dev/null +++ b/swig307-Fix-Ruby-trackings-code-to-use-C-hash.patch @@ -0,0 +1,202 @@ +From 0e725b5d9bd534964ae606852453df46d04037ee Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= +Date: Thu, 3 Jan 2013 11:56:25 +0100 +Subject: [PATCH] Fix Ruby tracking code to use C hash + +This is a patch to resolve SF bug 2034216 (Github issue #225) +The bug is that the tracking code uses a ruby hash and thus may +allocate objects (Bignum) while running the GC. This was tolerated in +1.8 but is invalid (raises an exception) in 1.9. +The patch uses a C hash (also used by ruby) instead. +--- + Lib/ruby/rubytracking.swg | 127 ++++++++++++++++++---------------------------- + 1 file changed, 49 insertions(+), 78 deletions(-) + +diff --git a/Lib/ruby/rubytracking.swg b/Lib/ruby/rubytracking.swg +index 0a36f4a..d974228 100644 +--- a/Lib/ruby/rubytracking.swg ++++ b/Lib/ruby/rubytracking.swg +@@ -22,19 +22,19 @@ extern "C" { + # error sizeof(void*) is not the same as long or long long + #endif + +- +-/* Global Ruby hash table to store Trackings from C/C++ ++/* Global hash table to store Trackings from C/C++ + structs to Ruby Objects. + */ +-static VALUE swig_ruby_trackings = Qnil; ++static st_table* swig_ruby_trackings = NULL; ++ ++VALUE get_swig_trackings_count(ANYARGS) { ++ return SWIG2NUM(swig_ruby_trackings->num_entries); ++} + +-/* Global variable that stores a reference to the ruby +- hash table delete function. */ +-static ID swig_ruby_hash_delete; + +-/* Setup a Ruby hash table to store Trackings */ ++/* Setup a hash table to store Trackings */ + SWIGRUNTIME void SWIG_RubyInitializeTrackings(void) { +- /* Create a ruby hash table to store Trackings from C++ ++ /* Create a hash table to store Trackings from C++ + objects to Ruby objects. */ + + /* Try to see if some other .so has already created a +@@ -43,87 +43,47 @@ 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 trackings_value = Qnil; ++ /* change the variable name so that we can mix modules ++ compiled with older SWIG's */ ++ ID trackings_id = rb_intern( "@__safetrackings__" ); + VALUE verbose = rb_gv_get("VERBOSE"); + rb_gv_set("VERBOSE", Qfalse); +- swig_ruby_trackings = rb_ivar_get( _mSWIG, trackings_id ); ++ trackings_value = rb_ivar_get( _mSWIG, trackings_id ); + rb_gv_set("VERBOSE", verbose); + +- /* No, it hasn't. Create one ourselves */ +- if ( swig_ruby_trackings == Qnil ) +- { +- swig_ruby_trackings = rb_hash_new(); +- rb_ivar_set( _mSWIG, trackings_id, swig_ruby_trackings ); +- } +- +- /* Now store a reference to the hash table delete function +- so that we only have to look it up once.*/ +- 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 +- and then store a reference to it using +- a Ruby number object. */ +- +- /* Convert the Object to a Ruby number */ +- return SWIG2NUM(object); +-} +- +-/* Get a Ruby object from a previously stored reference */ +-SWIGRUNTIME VALUE SWIG_RubyReferenceToObject(VALUE reference) { +- /* The provided Ruby number object is a reference +- to the Ruby object we want.*/ ++ /* The trick here is that we have to store the hash table ++ pointer in a Ruby variable. We do not want Ruby's GC to ++ treat this pointer as a Ruby object, so we convert it to ++ a Ruby numeric value. */ ++ if (trackings_value == Qnil) { ++ /* No, it hasn't. Create one ourselves */ ++ swig_ruby_trackings = st_init_numtable(); ++ rb_ivar_set( _mSWIG, trackings_id, SWIG2NUM(swig_ruby_trackings) ); ++ } ++ else { ++ swig_ruby_trackings = (st_table*)NUM2SWIG(trackings_value); ++ } + +- /* Convert the Ruby number to a Ruby object */ +- return NUM2SWIG(reference); ++ rb_define_virtual_variable("SWIG_TRACKINGS_COUNT", get_swig_trackings_count, NULL); + } + + /* Add a Tracking from a C/C++ struct to a Ruby object */ + SWIGRUNTIME void SWIG_RubyAddTracking(void* ptr, VALUE object) { +- /* In a Ruby hash table we store the pointer and +- the associated Ruby object. The trick here is +- that we cannot store the Ruby object directly - if +- we do then it cannot be garbage collected. So +- 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, object); + } + + /* 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); +- +- if (value == Qnil) { +- /* No object exists - return nil. */ +- return Qnil; ++ VALUE value; ++ ++ if (st_lookup(swig_ruby_trackings, (st_data_t)ptr, &value)) { ++ return value; + } + else { +- /* Convert this value to Ruby object */ +- return SWIG_RubyReferenceToObject(value); ++ return Qnil; + } + } + +@@ -132,12 +92,8 @@ 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); ++ /* Delete the object from the hash table */ ++ st_delete(swig_ruby_trackings, (st_data_t *)&ptr, NULL); + } + + /* This is a helper method that unlinks a Ruby object from its +@@ -147,10 +103,25 @@ SWIGRUNTIME void SWIG_RubyUnlinkObjects(void* ptr) { + VALUE object = SWIG_RubyInstanceFor(ptr); + + if (object != Qnil) { ++ if (TYPE(object) != T_DATA) ++ abort(); + DATA_PTR(object) = 0; + } + } + ++/* This is a helper method that iterates over all the trackings ++ passing the C++ object pointer and its related Ruby object ++ to the passed callback function. */ ++ ++/* Proxy method to abstract the internal trackings datatype */ ++static int _ruby_internal_iterate_callback(void* ptr, VALUE obj, void(*meth)(void* ptr, VALUE obj)) { ++ (*meth)(ptr, obj); ++ return ST_CONTINUE; ++} ++ ++SWIGRUNTIME void SWIG_RubyIterateTrackings( void(*meth)(void* ptr, VALUE obj) ) { ++ st_foreach(swig_ruby_trackings, (int (*)(ANYARGS))&_ruby_internal_iterate_callback, (st_data_t)meth); ++} + + #ifdef __cplusplus + } +-- +2.4.3 + diff --git a/swig307-Ruby-trackings-patch-tidy-up.patch b/swig307-Ruby-trackings-patch-tidy-up.patch new file mode 100644 index 0000000..48bc7cc --- /dev/null +++ b/swig307-Ruby-trackings-patch-tidy-up.patch @@ -0,0 +1,76 @@ +From e14b392596f453dc8f437de90e8d405a04d5df62 Mon Sep 17 00:00:00 2001 +From: William S Fulton +Date: Sun, 13 Sep 2015 13:25:29 +0100 +Subject: [PATCH] Ruby trackings patch tidy up and add changes entry + +Closes #225 +--- + Lib/ruby/rubytracking.swg | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/Lib/ruby/rubytracking.swg b/Lib/ruby/rubytracking.swg +index d974228..37789c1 100644 +--- a/Lib/ruby/rubytracking.swg ++++ b/Lib/ruby/rubytracking.swg +@@ -27,7 +27,7 @@ extern "C" { + */ + static st_table* swig_ruby_trackings = NULL; + +-VALUE get_swig_trackings_count(ANYARGS) { ++static VALUE swig_ruby_trackings_count(ANYARGS) { + return SWIG2NUM(swig_ruby_trackings->num_entries); + } + +@@ -45,7 +45,7 @@ SWIGRUNTIME void SWIG_RubyInitializeTrackings(void) { + */ + VALUE trackings_value = Qnil; + /* change the variable name so that we can mix modules +- compiled with older SWIG's */ ++ compiled with older SWIG's - this used to be called "@__trackings__" */ + ID trackings_id = rb_intern( "@__safetrackings__" ); + VALUE verbose = rb_gv_get("VERBOSE"); + rb_gv_set("VERBOSE", Qfalse); +@@ -60,12 +60,11 @@ SWIGRUNTIME void SWIG_RubyInitializeTrackings(void) { + /* No, it hasn't. Create one ourselves */ + swig_ruby_trackings = st_init_numtable(); + rb_ivar_set( _mSWIG, trackings_id, SWIG2NUM(swig_ruby_trackings) ); +- } +- else { ++ } else { + swig_ruby_trackings = (st_table*)NUM2SWIG(trackings_value); + } + +- rb_define_virtual_variable("SWIG_TRACKINGS_COUNT", get_swig_trackings_count, NULL); ++ rb_define_virtual_variable("SWIG_TRACKINGS_COUNT", swig_ruby_trackings_count, NULL); + } + + /* Add a Tracking from a C/C++ struct to a Ruby object */ +@@ -81,8 +80,7 @@ SWIGRUNTIME VALUE SWIG_RubyInstanceFor(void* ptr) { + + if (st_lookup(swig_ruby_trackings, (st_data_t)ptr, &value)) { + return value; +- } +- else { ++ } else { + return Qnil; + } + } +@@ -114,13 +112,13 @@ SWIGRUNTIME void SWIG_RubyUnlinkObjects(void* ptr) { + to the passed callback function. */ + + /* Proxy method to abstract the internal trackings datatype */ +-static int _ruby_internal_iterate_callback(void* ptr, VALUE obj, void(*meth)(void* ptr, VALUE obj)) { ++static int swig_ruby_internal_iterate_callback(void* ptr, VALUE obj, void(*meth)(void* ptr, VALUE obj)) { + (*meth)(ptr, obj); + return ST_CONTINUE; + } + + SWIGRUNTIME void SWIG_RubyIterateTrackings( void(*meth)(void* ptr, VALUE obj) ) { +- st_foreach(swig_ruby_trackings, (int (*)(ANYARGS))&_ruby_internal_iterate_callback, (st_data_t)meth); ++ st_foreach(swig_ruby_trackings, (int (*)(ANYARGS))&swig_ruby_internal_iterate_callback, (st_data_t)meth); + } + + #ifdef __cplusplus +-- +2.4.3 + diff --git a/swig307-Ruby-trackings-support-for-1.8.patch b/swig307-Ruby-trackings-support-for-1.8.patch new file mode 100644 index 0000000..61a569a --- /dev/null +++ b/swig307-Ruby-trackings-support-for-1.8.patch @@ -0,0 +1,29 @@ +From 604b3d009ce4ed170ebfcfb256fc5c91c08b1d0e Mon Sep 17 00:00:00 2001 +From: William S Fulton +Date: Sun, 13 Sep 2015 20:09:50 +0100 +Subject: [PATCH] Ruby trackings bug fix support for 1.8 + +Issue #225 +--- + Lib/ruby/rubytracking.swg | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/Lib/ruby/rubytracking.swg b/Lib/ruby/rubytracking.swg +index 37789c1..8f9f01b 100644 +--- a/Lib/ruby/rubytracking.swg ++++ b/Lib/ruby/rubytracking.swg +@@ -11,6 +11,11 @@ + extern "C" { + #endif + ++#if !defined(ST_DATA_T_DEFINED) ++/* Needs to be explicitly included for Ruby 1.8 and earlier */ ++#include ++#endif ++ + /* Ruby 1.8 actually assumes the first case. */ + #if SIZEOF_VOIDP == SIZEOF_LONG + # define SWIG2NUM(v) LONG2NUM((unsigned long)v) +-- +2.4.3 +