diff options
author | Stanislav Sedov <stas@FreeBSD.org> | 2009-06-02 17:25:37 +0000 |
---|---|---|
committer | Stanislav Sedov <stas@FreeBSD.org> | 2009-06-02 17:25:37 +0000 |
commit | 5d63ebd5f52a7a8b31ff3ab054c15a255c1fc2ba (patch) | |
tree | 693904715c58aa30bdcd6c762662bb9f2324ecf0 /lang/ruby18 | |
parent | 131cfb2df45055ea12b5c26a3c6ee05e14fe456d (diff) | |
download | ports-5d63ebd5f52a7a8b31ff3ab054c15a255c1fc2ba.tar.gz ports-5d63ebd5f52a7a8b31ff3ab054c15a255c1fc2ba.zip |
Notes
Diffstat (limited to 'lang/ruby18')
-rw-r--r-- | lang/ruby18/Makefile | 1 | ||||
-rw-r--r-- | lang/ruby18/distinfo | 6 | ||||
-rw-r--r-- | lang/ruby18/files/extra-patch-gc | 535 | ||||
-rw-r--r-- | lang/ruby18/files/patch-file-check-space | 11 | ||||
-rw-r--r-- | lang/ruby18/files/patch-lib_soap_mimemessage.rb | 11 | ||||
-rw-r--r-- | lang/ruby18/files/patch-ostruct-fix-frozen | 46 | ||||
-rw-r--r-- | lang/ruby18/files/patch-ostruct-recursion-test | 39 | ||||
-rw-r--r-- | lang/ruby18/files/patch-select-ebadf-fix | 106 |
8 files changed, 216 insertions, 539 deletions
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; + } + |