Fix Ruby tracking code (BZ#1225140)

This commit is contained in:
Jitka Plesnikova 2015-09-15 08:10:56 +02:00
parent 2fa3b57593
commit 0c140872c0
4 changed files with 324 additions and 11 deletions

View File

@ -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: 5%{?dist}
Release: 6%{?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 <jplesnik@redhat.com> - 3.0.7-6
- Fix Ruby tracking code (BZ#1225140)
* Thu Sep 03 2015 Jonathan Wakely <jwakely@redhat.com> - 3.0.7-5
- Rebuilt for Boost 1.59

View File

@ -0,0 +1,202 @@
From 0e725b5d9bd534964ae606852453df46d04037ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= <kkaempf@suse.de>
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

View File

@ -0,0 +1,76 @@
From e14b392596f453dc8f437de90e8d405a04d5df62 Mon Sep 17 00:00:00 2001
From: William S Fulton <wsf@fultondesigns.co.uk>
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

View File

@ -0,0 +1,29 @@
From 604b3d009ce4ed170ebfcfb256fc5c91c08b1d0e Mon Sep 17 00:00:00 2001
From: William S Fulton <wsf@fultondesigns.co.uk>
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 <st.h>
+#endif
+
/* Ruby 1.8 actually assumes the first case. */
#if SIZEOF_VOIDP == SIZEOF_LONG
# define SWIG2NUM(v) LONG2NUM((unsigned long)v)
--
2.4.3