aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Mk/bsd.ruby.mk4
-rw-r--r--lang/ruby18/Makefile1
-rw-r--r--lang/ruby18/distinfo6
-rw-r--r--lang/ruby18/files/extra-patch-gc535
-rw-r--r--lang/ruby18/files/patch-file-check-space11
-rw-r--r--lang/ruby18/files/patch-lib_soap_mimemessage.rb11
-rw-r--r--lang/ruby18/files/patch-ostruct-fix-frozen46
-rw-r--r--lang/ruby18/files/patch-ostruct-recursion-test39
-rw-r--r--lang/ruby18/files/patch-select-ebadf-fix106
9 files changed, 218 insertions, 541 deletions
diff --git a/Mk/bsd.ruby.mk b/Mk/bsd.ruby.mk
index b77bf7803c6e..117ae46b0414 100644
--- a/Mk/bsd.ruby.mk
+++ b/Mk/bsd.ruby.mk
@@ -170,9 +170,9 @@ RUBY?= ${LOCALBASE}/bin/${RUBY_NAME}
# Ruby 1.8
#
RUBY_RELVERSION= 1.8.7
-RUBY_PORTREVISION= 1
+RUBY_PORTREVISION= 0
RUBY_PORTEPOCH= 1
-RUBY_PATCHLEVEL= 72
+RUBY_PATCHLEVEL= 160
. if ${RUBY_PATCHLEVEL} == 0
RUBY_VERSION?= ${RUBY_RELVERSION}
diff --git a/lang/ruby18/Makefile b/lang/ruby18/Makefile
index 90d8f3412547..38751170a6c6 100644
--- a/lang/ruby18/Makefile
+++ b/lang/ruby18/Makefile
@@ -36,7 +36,6 @@ _RUBY_SYSLIBDIR= ${PREFIX}/lib
OPTIONS= PTHREADS "Enable pthreads support (may break some apps)" off \
ONIGURUMA "Build with oniguruma regular expressions lib" off \
- GCPATCH "Build with GC performance statistics collector" off \
IPV6 "Enable IPv6 support" on \
RDOC "Build and install Rdoc indexes" off \
DEBUG "Compile-in debug info" off
diff --git a/lang/ruby18/distinfo b/lang/ruby18/distinfo
index 45efb4bcc42e..99594eea178f 100644
--- a/lang/ruby18/distinfo
+++ b/lang/ruby18/distinfo
@@ -1,3 +1,3 @@
-MD5 (ruby/ruby-1.8.7-p72.tar.bz2) = 0b215c46b89b28d7ab8d56d96e72d5b9
-SHA256 (ruby/ruby-1.8.7-p72.tar.bz2) = a8f8a28e286dd76747d8e97ea5cfe7a315eb896906ab8c8606d687d9f6f6146e
-SIZE (ruby/ruby-1.8.7-p72.tar.bz2) = 4127450
+MD5 (ruby/ruby-1.8.7-p160.tar.bz2) = f8ddb886b8a81cf005f53e9a9541091d
+SHA256 (ruby/ruby-1.8.7-p160.tar.bz2) = e524a086212d2142c03eb6b82cd602adcac9dcf8bf60049e89aa4ca69864984d
+SIZE (ruby/ruby-1.8.7-p160.tar.bz2) = 4137518
diff --git a/lang/ruby18/files/extra-patch-gc b/lang/ruby18/files/extra-patch-gc
deleted file mode 100644
index 5b0aae90f5d3..000000000000
--- a/lang/ruby18/files/extra-patch-gc
+++ /dev/null
@@ -1,535 +0,0 @@
---- gc.c.orig 2006-10-30 04:35:55.000000000 +0100
-+++ gc.c 2006-11-06 20:25:12.562500000 +0100
-@@ -22,8 +22,16 @@
- #include <setjmp.h>
- #include <sys/types.h>
-
-+#ifdef _WIN32
-+#include <string.h>
-+#else
-+#include <strings.h>
-+#endif
-+
- #ifdef HAVE_SYS_TIME_H
- #include <sys/time.h>
-+#elif defined(_WIN32)
-+#include <time.h>
- #endif
-
- #ifdef HAVE_SYS_RESOURCE_H
-@@ -40,7 +48,6 @@
- #if !defined(setjmp) && defined(HAVE__SETJMP)
- #define setjmp(env) _setjmp(env)
- #endif
--
- /* Make alloca work the best possible way. */
- #ifdef __GNUC__
- # ifndef atarist
-@@ -159,8 +166,17 @@
- RUBY_CRITICAL(free(x));
- }
-
-+#if HAVE_LONG_LONG
-+#define GC_TIME_TYPE LONG_LONG
-+#else
-+#define GC_TIME_TYPE long
-+#endif
-+
- extern int ruby_in_compile;
- static int dont_gc;
-+static int gc_statistics = 0;
-+static GC_TIME_TYPE gc_time = 0;
-+static int gc_collections = 0;
- static int during_gc;
- static int need_call_final = 0;
- static st_table *finalizer_table = 0;
-@@ -195,7 +211,7 @@
- * Disables garbage collection, returning <code>true</code> if garbage
- * collection was already disabled.
- *
-- * GC.disable #=> false
-+ * GC.disable #=> false or true
- * GC.disable #=> true
- *
- */
-@@ -209,6 +225,104 @@
- return old;
- }
-
-+/*
-+ * call-seq:
-+ * GC.enable_stats => true or false
-+ *
-+ * Enables garbage collection statistics, returning <code>true</code> if garbage
-+ * collection statistics was already enabled.
-+ *
-+ * GC.enable_stats #=> false or true
-+ * GC.enable_stats #=> true
-+ *
-+ */
-+
-+VALUE
-+rb_gc_enable_stats()
-+{
-+ int old = gc_statistics;
-+ gc_statistics = Qtrue;
-+ return old;
-+}
-+
-+/*
-+ * call-seq:
-+ * GC.disable_stats => true or false
-+ *
-+ * Disables garbage collection statistics, returning <code>true</code> if garbage
-+ * collection statistics was already disabled.
-+ *
-+ * GC.disable_stats #=> false or true
-+ * GC.disable_stats #=> true
-+ *
-+ */
-+
-+VALUE
-+rb_gc_disable_stats()
-+{
-+ int old = gc_statistics;
-+ gc_statistics = Qfalse;
-+ return old;
-+}
-+
-+/*
-+ * call-seq:
-+ * GC.clear_stats => nil
-+ *
-+ * Clears garbage collection statistics, returning nil. This resets the number
-+ * of collections (GC.collections) and the time used (GC.time) to 0.
-+ *
-+ * GC.clear_stats #=> nil
-+ *
-+ */
-+
-+VALUE
-+rb_gc_clear_stats()
-+{
-+ gc_collections = 0;
-+ gc_time = 0;
-+ return Qnil;
-+}
-+
-+/*
-+ * call-seq:
-+ * GC.collections => Integer
-+ *
-+ * Returns the number of garbage collections performed while GC statistics collection
-+ * was enabled.
-+ *
-+ * GC.collections #=> 35
-+ *
-+ */
-+
-+VALUE
-+rb_gc_collections()
-+{
-+ return INT2NUM(gc_collections);
-+}
-+
-+/*
-+ * call-seq:
-+ * GC.time => Integer
-+ *
-+ * Returns the time spent during garbage collection while GC statistics collection
-+ * was enabled (in micro seconds).
-+ *
-+ * GC.time #=> 20000
-+ *
-+ */
-+
-+VALUE
-+rb_gc_time()
-+{
-+#if HAVE_LONG_LONG
-+ return LL2NUM(gc_time);
-+#else
-+ return LONG2NUM(gc_time);
-+#endif
-+}
-+
-+
- VALUE rb_mGC;
-
- static struct gc_list {
-@@ -300,7 +414,7 @@
- static RVALUE *freelist = 0;
- static RVALUE *deferred_final_list = 0;
-
--#define HEAPS_INCREMENT 10
-+static int heaps_increment = 10;
- static struct heaps_slot {
- void *membase;
- RVALUE *slot;
-@@ -309,13 +423,141 @@
- static int heaps_length = 0;
- static int heaps_used = 0;
-
--#define HEAP_MIN_SLOTS 10000
--static int heap_slots = HEAP_MIN_SLOTS;
-+static int heap_min_slots = 10000;
-+static int heap_slots = 10000;
-+
-+static int heap_free_min = 4096;
-+
-+static long initial_malloc_limit = GC_MALLOC_LIMIT;
-
--#define FREE_MIN 4096
-+static int verbose_gc_stats = Qfalse;
-+
-+static FILE* gc_data_file = NULL;
-
- static RVALUE *himem, *lomem;
-
-+static void set_gc_parameters()
-+{
-+ char *gc_stats_ptr, *min_slots_ptr, *free_min_ptr,
-+ *heap_incr_ptr, *malloc_limit_ptr, *gc_heap_file_ptr;
-+
-+ gc_data_file = stderr;
-+
-+ gc_stats_ptr = getenv("RUBY_GC_STATS");
-+ if (gc_stats_ptr != NULL) {
-+ int gc_stats_i = atoi(gc_stats_ptr);
-+ if (gc_stats_i > 0) {
-+ verbose_gc_stats = Qtrue;
-+ }
-+ }
-+
-+ gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE");
-+ if (gc_heap_file_ptr != NULL) {
-+ FILE* data_file = fopen(gc_heap_file_ptr, "w");
-+ if (data_file != NULL) {
-+ gc_data_file = data_file;
-+ }
-+ else {
-+ fprintf(stderr,
-+ "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr);
-+ }
-+ }
-+
-+ min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS");
-+ if (min_slots_ptr != NULL) {
-+ int min_slots_i = atoi(min_slots_ptr);
-+ if (verbose_gc_stats) {
-+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", min_slots_ptr);
-+ }
-+ if (min_slots_i > 0) {
-+ heap_slots = min_slots_i;
-+ heap_min_slots = min_slots_i;
-+ }
-+ }
-+
-+ free_min_ptr = getenv("RUBY_HEAP_FREE_MIN");
-+ if (free_min_ptr != NULL) {
-+ int free_min_i = atoi(free_min_ptr);
-+ if (verbose_gc_stats) {
-+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", free_min_ptr);
-+ }
-+ if (free_min_i > 0) {
-+ heap_free_min = free_min_i;
-+ }
-+ }
-+
-+ heap_incr_ptr = getenv("RUBY_HEAP_INCREMENT");
-+ if (heap_incr_ptr != NULL) {
-+ int heap_incr_i = atoi(heap_incr_ptr);
-+ if (verbose_gc_stats) {
-+ fprintf(gc_data_file, "RUBY_HEAP_INCREMENT=%s\n", heap_incr_ptr);
-+ }
-+ if (heap_incr_i > 0) {
-+ heaps_increment = heap_incr_i;
-+ }
-+ }
-+
-+ malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT");
-+ if (malloc_limit_ptr != NULL) {
-+ int malloc_limit_i = atol(malloc_limit_ptr);
-+ if (verbose_gc_stats) {
-+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", malloc_limit_ptr);
-+ }
-+ if (malloc_limit_i > 0) {
-+ initial_malloc_limit = malloc_limit_i;
-+ }
-+ }
-+}
-+
-+/*
-+ * call-seq:
-+ * GC.dump => nil
-+ *
-+ * dumps information about the current GC data structures to the GC log file
-+ *
-+ * GC.dump #=> nil
-+ *
-+ */
-+
-+VALUE
-+rb_gc_dump()
-+{
-+ int i;
-+
-+ for (i = 0; i < heaps_used; i++) {
-+ int heap_size = heaps[i].limit;
-+ fprintf(gc_data_file, "HEAP[%2d]: size=%7d\n", i, heap_size);
-+ }
-+
-+ return Qnil;
-+}
-+
-+/*
-+ * call-seq:
-+ * GC.log String => String
-+ *
-+ * Logs string to the GC data file and returns it.
-+ *
-+ * GC.log "manual GC call" #=> "manual GC call"
-+ *
-+ */
-+
-+VALUE
-+rb_gc_log(self, original_str)
-+ VALUE self, original_str;
-+{
-+ if (original_str == Qnil) {
-+ fprintf(gc_data_file, "\n");
-+ }
-+ else {
-+ VALUE str = StringValue(original_str);
-+ char *p = RSTRING(str)->ptr;
-+ fprintf(gc_data_file, "%s\n", p);
-+ }
-+ return original_str;
-+}
-+
-+
- static void
- add_heap()
- {
-@@ -326,7 +568,7 @@
- struct heaps_slot *p;
- int length;
-
-- heaps_length += HEAPS_INCREMENT;
-+ heaps_length += heaps_increment;
- length = heaps_length*sizeof(struct heaps_slot);
- RUBY_CRITICAL(
- if (heaps_used > 0) {
-@@ -342,10 +584,10 @@
- for (;;) {
- RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1)));
- if (p == 0) {
-- if (heap_slots == HEAP_MIN_SLOTS) {
-+ if (heap_slots == heap_min_slots) {
- rb_memerror();
- }
-- heap_slots = HEAP_MIN_SLOTS;
-+ heap_slots = heap_min_slots;
- continue;
- }
- heaps[heaps_used].membase = p;
-@@ -362,7 +604,7 @@
- if (himem < pend) himem = pend;
- heaps_used++;
- heap_slots *= 1.8;
-- if (heap_slots <= 0) heap_slots = HEAP_MIN_SLOTS;
-+ if (heap_slots <= 0) heap_slots = heap_min_slots;
-
- while (p < pend) {
- p->as.free.flags = 0;
-@@ -1015,6 +1257,39 @@
- }
- }
-
-+static char* obj_type(int tp)
-+{
-+ switch (tp) {
-+ case T_NIL : return "NIL";
-+ case T_OBJECT : return "OBJECT";
-+ case T_CLASS : return "CLASS";
-+ case T_ICLASS : return "ICLASS";
-+ case T_MODULE : return "MODULE";
-+ case T_FLOAT : return "FLOAT";
-+ case T_STRING : return "STRING";
-+ case T_REGEXP : return "REGEXP";
-+ case T_ARRAY : return "ARRAY";
-+ case T_FIXNUM : return "FIXNUM";
-+ case T_HASH : return "HASH";
-+ case T_STRUCT : return "STRUCT";
-+ case T_BIGNUM : return "BIGNUM";
-+ case T_FILE : return "FILE";
-+
-+ case T_TRUE : return "TRUE";
-+ case T_FALSE : return "FALSE";
-+ case T_DATA : return "DATA";
-+ case T_MATCH : return "MATCH";
-+ case T_SYMBOL : return "SYMBOL";
-+
-+ case T_BLKTAG : return "BLKTAG";
-+ case T_UNDEF : return "UNDEF";
-+ case T_VARMAP : return "VARMAP";
-+ case T_SCOPE : return "SCOPE";
-+ case T_NODE : return "NODE";
-+ default: return "____";
-+ }
-+}
-+
- static void
- free_unused_heaps()
- {
-@@ -1045,12 +1320,21 @@
- unsigned long live = 0;
- unsigned long free_min = 0;
-
-+ unsigned long really_freed = 0;
-+ int free_counts[256];
-+ int live_counts[256];
-+ int do_gc_stats = gc_statistics & verbose_gc_stats;
-+
- for (i = 0; i < heaps_used; i++) {
- free_min += heaps[i].limit;
- }
- free_min = free_min * 0.2;
-- if (free_min < FREE_MIN)
-- free_min = FREE_MIN;
-+ if (free_min < heap_free_min)
-+ free_min = heap_free_min;
-+
-+ if (do_gc_stats) {
-+ for (i = 0 ; i< 256; i++) { free_counts[i] = live_counts[i] = 0; }
-+ }
-
- if (ruby_in_compile && ruby_parser_stack_on_heap()) {
- /* should not reclaim nodes during compilation
-@@ -1083,6 +1367,9 @@
- if (!(p->as.basic.flags & FL_MARK)) {
- if (p->as.basic.flags) {
- obj_free((VALUE)p);
-+ if (do_gc_stats) {
-+ really_freed++;
-+ }
- }
- if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
- p->as.free.flags = FL_MARK; /* remain marked */
-@@ -1090,6 +1377,12 @@
- final_list = p;
- }
- else {
-+ if (do_gc_stats) {
-+ int obt = p->as.basic.flags & T_MASK;
-+ if (obt) {
-+ free_counts[obt]++;
-+ }
-+ }
- p->as.free.flags = 0;
- p->as.free.next = freelist;
- freelist = p;
-@@ -1103,6 +1396,9 @@
- else {
- RBASIC(p)->flags &= ~FL_MARK;
- live++;
-+ if (do_gc_stats) {
-+ live_counts[RANY((VALUE)p)->as.basic.flags & T_MASK]++;
-+ }
- }
- p++;
- }
-@@ -1121,7 +1417,7 @@
- }
- if (malloc_increase > malloc_limit) {
- malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
-- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
-+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit;
- }
- malloc_increase = 0;
- if (freed < free_min) {
-@@ -1129,6 +1425,20 @@
- }
- during_gc = 0;
-
-+ if (do_gc_stats) {
-+ fprintf(gc_data_file, "objects processed: %.7d\n", live+freed);
-+ fprintf(gc_data_file, "live objects : %.7d\n", live);
-+ fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed);
-+ fprintf(gc_data_file, "freed objects : %.7d\n", really_freed);
-+ for(i=0; i<256; i++) {
-+ if (free_counts[i]>0) {
-+ fprintf(gc_data_file,
-+ "kept %.7d / freed %.7d objects of type %s\n",
-+ live_counts[i], free_counts[i], obj_type(i));
-+ }
-+ }
-+ }
-+
- /* clear finalization list */
- if (final_list) {
- deferred_final_list = final_list;
-@@ -1323,6 +1633,7 @@
- struct gc_list *list;
- struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */
- jmp_buf save_regs_gc_mark;
-+ struct timeval gctv1, gctv2;
- SET_STACK_END;
-
- #ifdef HAVE_NATIVETHREAD
-@@ -1339,6 +1650,14 @@
- if (during_gc) return;
- during_gc++;
-
-+ if (gc_statistics) {
-+ gc_collections++;
-+ gettimeofday(&gctv1, NULL);
-+ if (verbose_gc_stats) {
-+ fprintf(gc_data_file, "Garbage collection started\n");
-+ }
-+ }
-+
- init_mark_stack();
-
- gc_mark((VALUE)ruby_current_node, 0);
-@@ -1414,6 +1733,17 @@
- } while (!MARK_STACK_EMPTY);
-
- gc_sweep();
-+
-+ if (gc_statistics) {
-+ GC_TIME_TYPE musecs_used;
-+ gettimeofday(&gctv2, NULL);
-+ musecs_used = ((GC_TIME_TYPE)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec);
-+ gc_time += musecs_used;
-+
-+ if (verbose_gc_stats) {
-+ fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000);
-+ }
-+ }
- }
-
- void
-@@ -1582,6 +1912,7 @@
- if (!rb_gc_stack_start) {
- Init_stack(0);
- }
-+ set_gc_parameters();
- add_heap();
- }
-
-@@ -2051,6 +2382,14 @@
- rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0);
- rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
-
-+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0);
-+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0);
-+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0);
-+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0);
-+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0);
-+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0);
-+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1);
-+
- rb_mObSpace = rb_define_module("ObjectSpace");
- rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1);
- rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0);
diff --git a/lang/ruby18/files/patch-file-check-space b/lang/ruby18/files/patch-file-check-space
new file mode 100644
index 000000000000..fbe9a41fa55a
--- /dev/null
+++ b/lang/ruby18/files/patch-file-check-space
@@ -0,0 +1,11 @@
+--- file.c 2009/05/26 12:15:23 23584
++++ file.c 2009/05/26 12:20:27 23585
+@@ -3035,7 +3035,7 @@
+ p = last;
+ break;
+ }
+- if (*last == '.') e = dot;
++ if (*last == '.' || dot > last) e = dot;
+ continue;
+ #else
+ e = p; /* get the last dot of the last component */
diff --git a/lang/ruby18/files/patch-lib_soap_mimemessage.rb b/lang/ruby18/files/patch-lib_soap_mimemessage.rb
new file mode 100644
index 000000000000..5399068c516a
--- /dev/null
+++ b/lang/ruby18/files/patch-lib_soap_mimemessage.rb
@@ -0,0 +1,11 @@
+--- lib/soap/mimemessage.rb 2009/05/26 12:20:36 23586
++++ lib/soap/mimemessage.rb 2009/05/26 12:22:37 23587
+@@ -232,7 +232,7 @@
+ end
+
+ def to_s
+- str = headers_str + "\r\n\r\n" + conent_str
++ str = headers_str + "\r\n\r\n" + content_str
+ end
+ end
+
diff --git a/lang/ruby18/files/patch-ostruct-fix-frozen b/lang/ruby18/files/patch-ostruct-fix-frozen
new file mode 100644
index 000000000000..a92eaa46a778
--- /dev/null
+++ b/lang/ruby18/files/patch-ostruct-fix-frozen
@@ -0,0 +1,46 @@
+--- lib/ostruct.rb 2009/05/26 12:00:53 23580
++++ lib/ostruct.rb 2009/05/26 12:06:21 23581
+@@ -67,28 +67,33 @@
+ @table.each_key{|key| new_ostruct_member(key)}
+ end
+
++ def modifiable
++ if self.frozen?
++ raise TypeError, "can't modify frozen #{self.class}", caller(2)
++ end
++ @table
++ end
++ protected :modifiable
++
+ def new_ostruct_member(name)
+ name = name.to_sym
+ unless self.respond_to?(name)
+- meta = class << self; self; end
+- meta.send(:define_method, name) { @table[name] }
+- meta.send(:define_method, :"#{name}=") { |x| @table[name] = x }
++ class << self; self; end.class_eval do
++ define_method(name) { @table[name] }
++ define_method("#{name}=") { |x| modifiable[name] = x }
++ end
+ end
++ name
+ end
+
+ def method_missing(mid, *args) # :nodoc:
+ mname = mid.id2name
+ len = args.length
+- if mname =~ /=$/
++ if mname.chomp!('=')
+ if len != 1
+ raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
+ end
+- if self.frozen?
+- raise TypeError, "can't modify frozen #{self.class}", caller(1)
+- end
+- mname.chop!
+- self.new_ostruct_member(mname)
+- @table[mname.intern] = args[0]
++ modifiable[new_ostruct_member(mname)] = args[0]
+ elsif len == 0
+ @table[mid]
+ else
diff --git a/lang/ruby18/files/patch-ostruct-recursion-test b/lang/ruby18/files/patch-ostruct-recursion-test
new file mode 100644
index 000000000000..3c3d1f54e62c
--- /dev/null
+++ b/lang/ruby18/files/patch-ostruct-recursion-test
@@ -0,0 +1,39 @@
+--- lib/ostruct.rb 2009/05/26 11:54:29 23578
++++ lib/ostruct.rb 2009/05/26 12:00:44 23579
+@@ -111,25 +111,23 @@
+ def inspect
+ str = "#<#{self.class}"
+
+- Thread.current[InspectKey] ||= []
+- if Thread.current[InspectKey].include?(self) then
+- str << " ..."
+- else
++ ids = (Thread.current[InspectKey] ||= [])
++ if ids.include?(object_id)
++ return str << ' ...>'
++ end
++
++ ids << object_id
++ begin
+ first = true
+ for k,v in @table
+ str << "," unless first
+ first = false
+-
+- Thread.current[InspectKey] << v
+- begin
+- str << " #{k}=#{v.inspect}"
+- ensure
+- Thread.current[InspectKey].pop
+- end
++ str << " #{k}=#{v.inspect}"
+ end
++ return str << '>'
++ ensure
++ ids.pop
+ end
+-
+- str << ">"
+ end
+ alias :to_s :inspect
+
diff --git a/lang/ruby18/files/patch-select-ebadf-fix b/lang/ruby18/files/patch-select-ebadf-fix
new file mode 100644
index 000000000000..c89483faafb2
--- /dev/null
+++ b/lang/ruby18/files/patch-select-ebadf-fix
@@ -0,0 +1,106 @@
+--- eval.c 2009/05/26 05:24:19 23576
++++ eval.c 2009/05/26 11:54:05 23577
+@@ -74,7 +74,16 @@
+
+ #include <time.h>
+
+-#ifdef __BEOS__
++#if defined(HAVE_FCNTL_H) || defined(_WIN32)
++#include <fcntl.h>
++#elif defined(HAVE_SYS_FCNTL_H)
++#include <sys/fcntl.h>
++#endif
++#ifdef __CYGWIN__
++#include <io.h>
++#endif
++
++#if defined(__BEOS__) && !defined(BONE)
+ #include <net/socket.h>
+ #endif
+
+@@ -11084,20 +11093,60 @@
+ #ifdef ERESTART
+ if (e == ERESTART) goto again;
+ #endif
+- FOREACH_THREAD_FROM(curr, th) {
+- if (th->wait_for & WAIT_SELECT) {
+- int v = 0;
+-
+- v |= find_bad_fds(&readfds, &th->readfds, th->fd);
+- v |= find_bad_fds(&writefds, &th->writefds, th->fd);
+- v |= find_bad_fds(&exceptfds, &th->exceptfds, th->fd);
+- if (v) {
+- th->select_value = n;
+- n = max;
+- }
+- }
+- }
+- END_FOREACH_FROM(curr, th);
++ if (e == EBADF) {
++ int badfd = -1;
++ int fd;
++ int dummy;
++ for (fd = 0; fd <= max; fd++) {
++ if ((FD_ISSET(fd, &readfds) ||
++ FD_ISSET(fd, &writefds) ||
++ FD_ISSET(fd, &exceptfds)) &&
++ fcntl(fd, F_GETFD, &dummy) == -1 &&
++ errno == EBADF) {
++ badfd = fd;
++ break;
++ }
++ }
++ if (badfd != -1) {
++ FOREACH_THREAD_FROM(curr, th) {
++ if (th->wait_for & WAIT_FD) {
++ if (th->fd == badfd) {
++ found = 1;
++ th->status = THREAD_RUNNABLE;
++ th->fd = 0;
++ break;
++ }
++ }
++ if (th->wait_for & WAIT_SELECT) {
++ if (FD_ISSET(badfd, &th->readfds) ||
++ FD_ISSET(badfd, &th->writefds) ||
++ FD_ISSET(badfd, &th->exceptfds)) {
++ found = 1;
++ th->status = THREAD_RUNNABLE;
++ th->select_value = -EBADF;
++ break;
++ }
++ }
++ }
++ END_FOREACH_FROM(curr, th);
++ }
++ }
++ else {
++ FOREACH_THREAD_FROM(curr, th) {
++ if (th->wait_for & WAIT_SELECT) {
++ int v = 0;
++
++ v |= find_bad_fds(&readfds, &th->readfds, th->fd);
++ v |= find_bad_fds(&writefds, &th->writefds, th->fd);
++ v |= find_bad_fds(&exceptfds, &th->exceptfds, th->fd);
++ if (v) {
++ th->select_value = n;
++ n = max;
++ }
++ }
++ }
++ END_FOREACH_FROM(curr, th);
++ }
+ }
+ if (select_timeout && n == 0) {
+ if (now < 0.0) now = timeofday();
+@@ -11408,6 +11457,10 @@
+ if (read) *read = curr_thread->readfds;
+ if (write) *write = curr_thread->writefds;
+ if (except) *except = curr_thread->exceptfds;
++ if (curr_thread->select_value < 0) {
++ errno = -curr_thread->select_value;
++ return -1;
++ }
+ return curr_thread->select_value;
+ }
+