[前][次][番号順一覧][スレッド一覧]

ruby-changes:6758

From: nobu <ko1@a...>
Date: Thu, 31 Jul 2008 01:07:41 +0900 (JST)
Subject: [ruby-changes:6758] Ruby:r18274 (mvm): * merged from trunk r18206:18273.

nobu	2008-07-31 01:06:57 +0900 (Thu, 31 Jul 2008)

  New Revision: 18274

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=18274

  Log:
    * merged from trunk r18206:18273.

  Added files:
    branches/mvm/ext/win32ole/sample/ienavi2.rb
    branches/mvm/test/rss/dot.png
    branches/mvm/test/ruby/enc/test_koi8.rb
    branches/mvm/test/ruby/test_sleep.rb
    branches/mvm/test/win32ole/err_in_callback.rb
    branches/mvm/test/win32ole/test_err_in_callback.rb
  Removed files:
    branches/mvm/test/ruby/test_koi8.rb
  Modified files:
    branches/mvm/.merged-trunk-revision
    branches/mvm/ChangeLog
    branches/mvm/bootstraptest/test_method.rb
    branches/mvm/dir.c
    branches/mvm/dln.c
    branches/mvm/dln.h
    branches/mvm/ext/bigdecimal/bigdecimal.c
    branches/mvm/ext/win32ole/win32ole.c
    branches/mvm/file.c
    branches/mvm/gc.c
    branches/mvm/include/ruby/ruby.h
    branches/mvm/io.c
    branches/mvm/lib/rinda/tuplespace.rb
    branches/mvm/lib/webrick/httputils.rb
    branches/mvm/math.c
    branches/mvm/pack.c
    branches/mvm/parse.y
    branches/mvm/proc.c
    branches/mvm/regint.h
    branches/mvm/regparse.c
    branches/mvm/sample/exyacc.rb
    branches/mvm/string.c
    branches/mvm/test/etc/test_etc.rb
    branches/mvm/test/openssl/test_ssl.rb
    branches/mvm/test/rinda/test_rinda.rb
    branches/mvm/test/rss/rss-assertions.rb
    branches/mvm/test/rss/test_atom.rb
    branches/mvm/test/ruby/test_io.rb
    branches/mvm/test/ruby/test_io_m17n.rb
    branches/mvm/test/ruby/test_math.rb
    branches/mvm/test/ruby/test_require.rb
    branches/mvm/test/win32ole/test_win32ole_event.rb
    branches/mvm/thread.c
    branches/mvm/version.h
    branches/mvm/vm.c
    branches/mvm/vm_core.h
    branches/mvm/win32/win32.c

Index: mvm/regparse.c
===================================================================
--- mvm/regparse.c	(revision 18273)
+++ mvm/regparse.c	(revision 18274)
@@ -729,7 +729,10 @@
     CHECK_NULL_RETURN_MEMERR(e);
 
     e->name = strdup_with_null(reg->enc, name, name_end);
-    if (IS_NULL(e->name)) return ONIGERR_MEMORY;
+    if (IS_NULL(e->name)) {
+      xfree(e);
+      return ONIGERR_MEMORY;
+    }
     onig_st_insert_strend(t, e->name, (e->name + (name_end - name)),
                           (HashDataType )e);
 
@@ -5392,6 +5395,9 @@
       if (r == 0) {
 	*targetp = qn;
       }
+      else if (r == 1) {
+        onig_node_free(qn);
+      }
       else if (r == 2) { /* split case: /abc+/ */
 	Node *tmp;
 
Index: mvm/math.c
===================================================================
--- mvm/math.c	(revision 18273)
+++ mvm/math.c	(revision 18274)
@@ -51,6 +51,24 @@
     }
 }
 
+static void
+infinity_check(VALUE arg, double res, const char *msg)
+{
+    while(1) {
+	if (errno) {
+	    rb_sys_fail(msg);
+	}
+	if (isinf(res) && !isinf(RFLOAT_VALUE(arg))) {
+#if defined(EDOM)
+	    errno = EDOM;
+#elif defined(ERANGE)
+	    errno = ERANGE;
+#endif
+	    continue;
+	}
+	break;
+    }
+}
 
 /*
  *  call-seq:
@@ -286,6 +304,7 @@
     errno = 0;
     d = atanh(RFLOAT_VALUE(x));
     domain_check(d, "atanh");
+    infinity_check(x, d, "atanh");
     return DOUBLE2NUM(d);
 }
 
@@ -337,6 +356,7 @@
 	d /= log(RFLOAT_VALUE(base));
     }
     domain_check(d, "log");
+    infinity_check(x, d, "log");
     return DOUBLE2NUM(d);
 }
 
@@ -367,9 +387,8 @@
     Need_Float(x);
     errno = 0;
     d = log2(RFLOAT_VALUE(x));
-    if (errno) {
-	rb_sys_fail("log2");
-    }
+    domain_check(d, "log2");
+    infinity_check(x, d, "log2");
     return DOUBLE2NUM(d);
 }
 
@@ -389,6 +408,7 @@
     errno = 0;
     d = log10(RFLOAT_VALUE(x));
     domain_check(d, "log10");
+    infinity_check(x, d, "log10");
     return DOUBLE2NUM(d);
 }
 
Index: mvm/include/ruby/ruby.h
===================================================================
--- mvm/include/ruby/ruby.h	(revision 18273)
+++ mvm/include/ruby/ruby.h	(revision 18274)
@@ -302,6 +302,7 @@
     RUBY_T_UNDEF  = 0x1b,
     RUBY_T_NODE   = 0x1c,
     RUBY_T_ICLASS = 0x1d,
+    RUBY_T_DEFERRED = 0x1e,
 
     RUBY_T_MASK   = 0x1f
 };
@@ -330,6 +331,7 @@
 #define T_COMPLEX RUBY_T_COMPLEX
 #define T_UNDEF  RUBY_T_UNDEF
 #define T_NODE   RUBY_T_NODE
+#define T_DEFERRED RUBY_T_DEFERRED
 #define T_MASK   RUBY_T_MASK
 
 #define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
Index: mvm/ChangeLog
===================================================================
--- mvm/ChangeLog	(revision 18273)
+++ mvm/ChangeLog	(revision 18274)
@@ -1,3 +1,246 @@
+Thu Jul 31 00:58:33 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* pack.c (pack_unpack): reduced static variables.
+
+Thu Jul 31 00:10:20 2008  Yusuke Endoh  <mame@t...>
+
+	* proc.c (rb_proc_call_with_block): prevent null reference.
+
+Wed Jul 30 22:19:13 2008  Yusuke Endoh  <mame@t...>
+
+	* parse.y (vtable_free): remove meaningless null check.
+
+Wed Jul 30 22:08:25 2008  Tanaka Akira  <akr@f...>
+
+	* dir.c (struct dir_data): change path field char * to VALUE.
+	  (mark_dir): new function for mark path field.
+	  (free_dir): follow the path field change.
+	  (dir_s_alloc): ditto.
+	  (dir_initialize): ditto.
+	  (dir_s_open): ditto.
+	  (dir_inspect): ditto.
+	  (dir_path): return (duplicate of) the path field to preserve
+	  encoding.  [ruby-dev:35685]
+
+Wed Jul 30 22:06:56 2008  Yusuke Endoh  <mame@t...>
+
+	* string.c (sym_inspect): remove dead code.
+
+Wed Jul 30 21:32:52 2008  Yusuke Endoh  <mame@t...>
+
+	* ChangeLog: fix wrong method name and add reference.
+
+Wed Jul 30 21:30:08 2008  Yusuke Endoh  <mame@t...>
+
+	* regparse.c (name_add): fix memory leak.
+
+Wed Jul 30 21:08:06 2008  Yusuke Endoh  <mame@t...>
+
+	* regparse.c (parse_exp): fix memory leak at Regexp.new("x{1,1}").
+
+Wed Jul 30 17:48:15 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* win32/win32.c (rb_w32_select): recalc the rest of timeout for each
+	  iterations.  [ruby-core:18015]
+
+Tue Jul 29 23:37:37 2008  Yusuke Endoh  <mame@t...>
+
+	* io.c (io_ungetc): raise NotImplementedError when ungetc is called
+	  against dummy encoding IO.  [ruby-dev:35686]
+
+	* io.c (rb_io_getline_1): ditto when gets with delimiter is called.
+
+	* io.c (io_getc): ditto when getc is called.
+
+	* test/ruby/test_io_m17n.rb (test_terminator_stateful_conversion,
+	  test_getc_stateful_conversion, test_ungetc_stateful_conversion):
+	  these tests should raise NotImplementedError.
+
+Tue Jul 29 22:55:34 2008  Yusuke Endoh  <mame@t...>
+
+	* test/ruby/test_io.rb (pipe): run reader thread and writer thread.
+
+Tue Jul 29 21:38:08 2008  Yusuke Endoh  <mame@t...>
+
+	* ext/bigdecimal/bigdecimal.c (Init_bigdecimal): fix typo.
+
+Tue Jul 29 21:35:59 2008  Yusuke Endoh  <mame@t...>
+
+	* test/etc/test_etc.rb (test_passwd): age field may be string under
+	  some environments.
+
+Tue Jul 29 17:54:35 2008  NARUSE, Yui  <naruse@r...>
+
+	* dir.c (char_casecmp): fix: return 0 if either of characters is NUL.
+
+Tue Jul 29 13:17:03 2008  NARUSE, Yui  <naruse@r...>
+
+	* test/etc/test_etc.rb (test_getpwuid): fix for users whose uid is
+	  shared. 
+
+Tue Jul 29 05:37:53 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* file.c (rb_find_file_ext, rb_find_file): explicit relative path
+	  which starts with "./" or "../" should be searched from cwd
+	  instead of load path.  [ruby-dev:35673]
+
+Tue Jul 29 02:39:46 2008  NARUSE, Yui  <naruse@r...>
+
+	* math.c (math_atanh): raise EDOM on FreeBSD when atanh(1).
+
+	* math.c (math_log): ditto.
+
+	* math.c (math_log2): ditto.
+
+	* math.c (math_log10): ditto.
+
+	* test/ruby/test_math.rb: test for above.
+
+Tue Jul 29 01:41:15 2008  Tanaka Akira  <akr@f...>
+
+	* dir.c (struct dir_data): intenc field removed.
+	  (dir_s_alloc): intenc initialization removed.
+	  (dir_initialize): :internal_encoding option removed.  dirname code
+	  conversion removed.
+	  (dir_enc_str): code conversion removed.
+	  [ruby-dev:35661]
+
+Mon Jul 28 21:32:17 2008  Kouhei Sutou  <kou@c...>
+
+	* test/rss/: use PNG instead of zlib as binary data.
+
+Mon Jul 28 21:24:33 2008  NAKAMURA Usaku  <usa@r...>
+
+	* thread_win32.[ch] (cond_every_entry, rb_thread_cond_struct): reverted
+	  r18239 because r18245 made the changes unnecessary.
+
+	* thread.c (rb_mutex_struct): define after including thread_{pthread,
+	  win32}.c.
+
+Mon Jul 28 21:00:10 2008  Yusuke Endoh  <mame@t...>
+
+	* test/ruby/test_require.rb (test_require_too_long_filename):
+	  Kernel#require does not use dln_find_file_r (at r18242).
+
+Mon Jul 28 20:17:03 2008  Yusuke Endoh  <mame@t...>
+
+	* vm_core.h: move the definition of struct rb_mutex_struct.
+
+	* thread.c: ditto.
+
+Mon Jul 28 18:58:46 2008  Yusuke Endoh  <mame@t...>
+
+	* thread.c (mutex_unlock): fix typo.
+
+Mon Jul 28 18:15:45 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* file.c (rb_find_file_ext, rb_find_file): not to split load path with
+	  path separator.  [ruby-Bugs-21356]
+
+Mon Jul 28 18:14:03 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* win32/win32.c (overlapped_socket_io, fcntl, rb_w32_close): must not
+	  pass a pointer to int which is smaller than st_data_t on mswin64.
+
+Mon Jul 28 16:49:47 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* win32/win32.c (CreateChild, overlapped_socket_io): suppress
+	  warnings.
+
+Mon Jul 28 16:06:36 2008  NAKAMURA Usaku  <usa@r...>
+
+	* win32/win32.c (MAXPATHLEN): define before use.
+
+Mon Jul 28 16:01:12 2008  NAKAMURA Usaku  <usa@r...>
+
+	* thread_win32.[ch] (cond_every_entry, rb_thread_cond_struct): moved
+	  the definitions from .c to .h because rb_thread_cond_struct is used
+	  in vm_core.h.
+
+Mon Jul 28 14:29:54 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* dln.c (load_lib): use dln_find_file_r instead of dln_find_file.
+
+Mon Jul 28 00:18:47 2008  Yusuke Endoh  <mame@t...>
+
+	* vm_core.h, thread.c: It is now prohibited to use Data_Get_Struct in
+	  *_free against an object that is going to be free'ed.  So, change type
+	  of thread_t#keeping_mutexes from VALUE to mutex_t.
+
+	* vm.c: remove mark to keeping_mutexes.
+
+Sun Jul 27 23:32:42 2008  Yusuke Endoh  <mame@t...>
+
+	* test/openssl/test_ssl.rb (server_loop): rescue Errno::EINVAL and
+	  Errno::ECONNABORTED.
+
+Sun Jul 27 22:11:57 2008  NARUSE, Yui  <naruse@r...>
+
+	* bootstraptests/method.rb: increase RLIMIT_STACK size to 4M+8Kbytes
+	  because FreeBSD fails this less than that.
+
+Sun Jul 27 21:45:59 2008  Koichi Sasada  <ko1@a...>
+
+	* gc.c (gc_mark_children, obj_free): T_DEFERRED should not be appear.
+
+	* gc.c (gc_sweep, finalize_list): fix to decrement heap_slot#limit
+	  after executing finalizer.
+
+Sun Jul 27 14:48:37 2008  Koichi Sasada  <ko1@a...>
+
+	* include/ruby/ruby.h: add a type T_DEFERRED.
+
+	* gc.c: fix deferred finalizer system.  finalize processes of
+	  T_DATA and T_FILE are executed after gc process.
+	  And fix to use BUILTIN_TYPE() instead of seeing flag.
+
+	* thread.c, vm_core.h: add RUBY_VM_SET_FINALIZER_INTERRUPT()
+	  and check intterupt_flag at rb_thread_execute_interrupts().
+
+	* thread.c (mutex_mark): fix to mark next_mutex.
+
+	* vm.c (rb_thread_mark): fix to mark keeping_mutexes.
+
+Sun Jul 27 09:15:28 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* dln.h (dln_find_exe, dln_find_file): deprecated, use reentrant
+	  versions instead.
+
+Sun Jul 27 09:02:32 2008  Masatoshi SEKI  <m_seki@m...>
+
+	* lib/rinda/tuplespace.rb: merged from 1.8.
+
+	* test/rinda/test_rinda.rb: merged from 1.8.
+
+Sat Jul 26 22:45:18 2008  Yuki Sonoda (Yugui)  <yugui@y...>
+
+	* sample/exyacc.rb: fixed NoMethodError(Kernel#sub!).
+	  replaced use of special variables with explicit IO 
+	  operations.
+
+Sat Jul 26 21:17:18 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* ext/win32ole/win32ole.c (Init_win32ole): add
+	  WIN32OLE_EVENT#handler=, WIN32OLE_EVENT#handler
+
+	* test/win32ole/test_win32ole_event.rb: ditto.
+
+Sat Jul 26 07:44:14 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* ext/win32ole/win32ole.c (add_event_call_back): remove unused 
+	  variable.
+
+Fri Jul 25 23:48:10 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* gc.c (gc_sweep, obj_free, run_final): defer finalizers of IO and
+	  Data.  [ruby-dev:35578]
+
+Fri Jul 25 23:35:18 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* lib/webrick/httputils.rb (WEBrick::HTTPUtils#split_header_value):
+	  reduce backtrack.  based on a fix by Christian Neukirchen
+	  <chneukirchen AT gmail.com>.
+
 Fri Jul 25 23:24:07 2008  Nobuyoshi Nakada  <nobu@r...>
 
 	* thread_pthread.c (get_stack): subtract guard size.
@@ -12,6 +255,35 @@
 
 	* signal.c (sigsegv): use ruby_stack_overflowed_p.
 
+Fri Jul 25 21:55:38 2008  Yusuke Endoh  <mame@t...>
+
+	* test/ruby/enc/test_koi8.rb: move from test/ruby/test_koi8.rb.
+
+Fri Jul 25 21:09:32 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* ext/win32ole/win32ole.c (ole_invoke, add_event_callback,
+	  rescue_callback): refactoring.
+
+Fri Jul 25 20:52:44 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* test/win32ole/err_in_callback.rb : add test of raising
+	  exception in WIN32OLE_EVENT callback.
+
+	* test/win32ole/test_err_in_callback.rb : ditto.
+
+Fri Jul 25 20:43:57 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* ext/win32ole/win32ole.c (Init_win32ole): add
+	  WIN32OLE_EVENT#off_event.
+
+	* test/win32ole/test_win32ole_event.rb: ditto.
+
+	* test/win32ole/test_win32ole_event.rb: some refactoring.
+
+Fri Jul 25 19:50:49 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* regint.c (xmalloc, xrealloc, xfree): not to use ruby managed memory.
+
 Fri Jul 25 16:21:14 2008  Nobuyoshi Nakada  <nobu@r...>
 
 	* include/ruby/io.h (ruby_absolute_path_p): published.
@@ -22,6 +294,11 @@
 
 	* util.c (ruby_sys_getcwd): renamed and reverted.
 
+Fri Jul 25 15:52:40 2008  Koichi Sasada  <ko1@a...>
+
+	* vm.c (vm_invoke_proc): skip setting safe_level if
+	  it from bmethod.  This change makes test/ruby/test_proc.rb pass.
+
 Fri Jul 25 10:00:00 2008  Martin Duerst  <duerst@i...>
 
 	* test/ruby/test_transcode.rb: refactoring/cleanup of
@@ -1852,8 +2129,8 @@
 
 Fri Jun 20 03:19:39 2008  Yusuke Endoh  <mame@t...>
 
-	* test/testunit/collector/test_dir.rb: r15825 made it unnecessary to change
-	  String to Symbol.
+	* test/testunit/collector/test_dir.rb: r15825 made it unnecessary to
+	  change String to Symbol.
 
 	* test/testunit/collector/test_objectspace.rb: ditto.
 
Index: mvm/bootstraptest/test_method.rb
===================================================================
--- mvm/bootstraptest/test_method.rb	(revision 18273)
+++ mvm/bootstraptest/test_method.rb	(revision 18274)
@@ -997,12 +997,13 @@
 
 assert_normal_exit %q{
   begin
-    Process.setrlimit(Process::RLIMIT_STACK, 1024*1024)
+    Process.setrlimit(Process::RLIMIT_STACK, 4_202_496)
+    # FreeBSD fails this less than 4M + 8K bytes.
   rescue Exception
     exit
   end
   class C
-    attr "a" * (2*1024*1024)
+    attr "a" * (10*1024*1024)
   end
 }, '[ruby-dev:31818]'
 
Index: mvm/vm_core.h
===================================================================
--- mvm/vm_core.h	(revision 18273)
+++ mvm/vm_core.h	(revision 18274)
@@ -419,6 +419,8 @@
     void *arg;
 };
 
+struct rb_mutex_struct;
+
 struct rb_thread_struct
 {
     VALUE self;
@@ -466,7 +468,7 @@
     rb_thread_lock_t interrupt_lock;
     struct rb_unblock_callback unblock;
     VALUE locking_mutex;
-    VALUE keeping_mutexes;
+    struct rb_mutex_struct *keeping_mutexes;
     int transition_for_lock;
 
     struct rb_vm_tag *tag;
@@ -726,12 +728,13 @@
 
 #define RUBY_VM_SET_INTERRUPT(th) ((th)->interrupt_flag |= 0x02)
 #define RUBY_VM_SET_TIMER_INTERRUPT(th) ((th)->interrupt_flag |= 0x01)
+#define RUBY_VM_SET_FINALIZER_INTERRUPT(th) ((th)->interrupt_flag |= 0x04)
 #define RUBY_VM_INTERRUPTED(th) ((th)->interrupt_flag & 0x02)
 
 void rb_thread_execute_interrupts(rb_thread_t *);
 
 #define RUBY_VM_CHECK_INTS_TH(th) do { \
-  if(th->interrupt_flag){ \
+  if (th->interrupt_flag) { \
     /* TODO: trap something event */ \
     rb_thread_execute_interrupts(th); \
   } \
Index: mvm/sample/exyacc.rb
===================================================================
--- mvm/sample/exyacc.rb	(revision 18273)
+++ mvm/sample/exyacc.rb	(revision 18274)
@@ -2,21 +2,19 @@
 # usage: exyacc.rb [yaccfiles]
 # this is coverted from exyacc.pl in the camel book
 
-$/ = nil
-
-while gets()
-  sbeg = $_.index("\n%%") + 1
-  send = $_.rindex("\n%%") + 1
-  $_ = $_[sbeg, send-sbeg]
-  sub!(/.*\n/, "")
-  gsub!(/'\{'/, "'\001'")
-  gsub!(/'\}'/, "'\002'")
-  gsub!(%r{\*/}, "\003\003")
-  gsub!(%r{/\*[^\003]*\003\003}, '')
-  while gsub!(/\{[^{}]*\}/, ''); end
-  gsub!(/'\001'/, "'{'")
-  gsub!(/'\002'/, "'}'")
-  while gsub!(/^[ \t]*\n(\s)/, '\1'); end
-  gsub!(/([:|])[ \t\n]+(\w)/, '\1 \2')
-  print $_
+ARGF.each(nil) do |source|
+  sbeg = source.index("\n%%") + 1
+  send = source.rindex("\n%%") + 1
+  grammer = source[sbeg, send-sbeg]
+  grammer.sub!(/.*\n/, "")
+  grammer.gsub!(/'\{'/, "'\001'")
+  grammer.gsub!(/'\}'/, "'\002'")
+  grammer.gsub!(%r{\*/}, "\003\003")
+  grammer.gsub!(%r{/\*[^\003]*\003\003}, '')
+  while grammer.gsub!(/\{[^{}]*\}/, ''); end
+  grammer.gsub!(/'\001'/, "'{'")
+  grammer.gsub!(/'\002'/, "'}'")
+  while grammer.gsub!(/^[ \t]*\n(\s)/, '\1'); end
+  grammer.gsub!(/([:|])[ \t\n]+(\w)/, '\1 \2')
+  print grammer
 end
Index: mvm/string.c
===================================================================
--- mvm/string.c	(revision 18273)
+++ mvm/string.c	(revision 18274)
@@ -6352,7 +6352,7 @@
 static VALUE
 sym_inspect(VALUE sym)
 {
-    VALUE str, klass = Qundef;
+    VALUE str;
     ID id = SYM2ID(sym);
     rb_encoding *enc;
 
@@ -6366,10 +6366,6 @@
 	str = rb_str_inspect(str);
 	strncpy(RSTRING_PTR(str), ":\"", 2);
     }
-    if (klass != Qundef) {
-	rb_str_cat2(str, "/");
-	rb_str_append(str, rb_inspect(klass));
-    }
     return str;
 }
 
Index: mvm/io.c
===================================================================
--- mvm/io.c	(revision 18273)
+++ mvm/io.c	(revision 18274)
@@ -321,11 +321,17 @@
     return;
 }
 
+static rb_encoding *io_input_encoding(rb_io_t *fptr);
+
 static void
 io_ungetc(VALUE str, rb_io_t *fptr)
 {
     int len = RSTRING_LEN(str);
 
+    if (rb_enc_dummy_p(io_input_encoding(fptr))) {
+	rb_raise(rb_eNotImpError, "ungetc against dummy encoding is not currently supported");
+    }
+
     if (fptr->rbuf == NULL) {
         fptr->rbuf_off = 0;
         fptr->rbuf_len = 0;
@@ -1948,6 +1954,9 @@
 
     GetOpenFile(io, fptr);
     rb_io_check_readable(fptr);
+    if (rb_enc_dummy_p(io_input_encoding(fptr)) && rs != rb_default_rs) {
+	rb_raise(rb_eNotImpError, "gets with delimiter against dummy encoding is not currently supported");
+    }
     if (NIL_P(rs)) {
 	str = read_all(fptr, 0, Qnil);
 	if (RSTRING_LEN(str) == 0) return Qnil;
@@ -2263,6 +2272,10 @@
     int r, n, cr = 0;
     VALUE str;
 
+    if (rb_enc_dummy_p(enc)) {
+	rb_raise(rb_eNotImpError, "getc against dummy encoding is not currently supported");
+    }
+
     if (io_fillbuf(fptr) < 0) {
 	return Qnil;
     }
Index: mvm/pack.c
===================================================================
--- mvm/pack.c	(revision 18273)
+++ mvm/pack.c	(revision 18274)
@@ -1787,33 +1787,31 @@
 		VALUE buf = infected_str_new(0, (send - s)*3/4, str);
 		char *ptr = RSTRING_PTR(buf);
 		int a = -1,b = -1,c = 0,d;
-		static int first = 1;
-		static int b64_xtable[256];
+		static signed char b64_xtable[256];
 
-		if (first) {
+		if (b64_xtable['/'] <= 0) {
 		    int i;
-		    first = 0;
 
 		    for (i = 0; i < 256; i++) {
 			b64_xtable[i] = -1;
 		    }
 		    for (i = 0; i < 64; i++) {
-			b64_xtable[(int)b64_table[i]] = i;
+			b64_xtable[(unsigned char)b64_table[i]] = i;
 		    }
 		}
 		while (s < send) {
 		    a = b = c = d = -1;
-		    while((a = b64_xtable[(int)(*(unsigned char*)s)]) == -1 && s < send) { s++; }
-		    if( s >= send ) break;
+		    while ((a = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
+		    if (s >= send) break;
 		    s++;
-		    while((b = b64_xtable[(int)(*(unsigned char*)s)]) == -1 && s < send) { s++; }
-		    if( s >= send ) break;
+		    while ((b = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
+		    if (s >= send) break;
 		    s++;
-		    while((c = b64_xtable[(int)(*(unsigned char*)s)]) == -1 && s < send) { if( *s == '=' ) break; s++; }
-		    if( *s == '=' || s >= send ) break;
+		    while ((c = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
+		    if (*s == '=' || s >= send) break;
 		    s++;
-		    while((d = b64_xtable[(int)(*(unsigned char*)s)]) == -1 && s < send) { if( *s == '=' ) break; s++; }
-		    if( *s == '=' || s >= send ) break;
+		    while ((d = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
+		    if (*s == '=' || s >= send) break;
 		    s++;
 		    *ptr++ = a << 2 | b >> 4;
 		    *ptr++ = b << 4 | c >> 2;
Index: mvm/lib/webrick/httputils.rb
===================================================================
--- mvm/lib/webrick/httputils.rb	(revision 18273)
+++ mvm/lib/webrick/httputils.rb	(revision 18274)
@@ -23,16 +23,8 @@
       ret = path.dup
 
       ret.gsub!(%r{/+}o, '/')                    # //      => /
-      while ret.sub!(%r{/\.(/|\Z)}o, '/'); end   # /.      => /
-      begin                                      # /foo/.. => /foo
-        match = ret.sub!(%r{/([^/]+)/\.\.(/|\Z)}o){
-          if $1 == ".."
-            raise "abnormal path `#{path}'"
-          else
-            "/"
-          end
-        }
-      end while match
+      while ret.sub!(%r'/\.(?:/|\Z)', '/'); end  # /.      => /
+      while ret.sub!(%r'/(?!\.\./)[^/]+/\.\.(?:/|\Z)', '/'); end # /foo/.. => /foo
 
       raise "abnormal path `#{path}'" if %r{/\.\.(/|\Z)} =~ ret
       ret
@@ -155,8 +147,8 @@
     module_function :parse_header
 
     def split_header_value(str)
-      str.scan(/((?:"(?:\\.|[^"])+?"|[^",]+)+)
-                (?:,\s*|\Z)/xn).collect{|v| v[0] }
+      str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+)
+                    (?:,\s*|\Z)'xn).flatten
     end
     module_function :split_header_value
 
Index: mvm/lib/rinda/tuplespace.rb
===================================================================
--- mvm/lib/rinda/tuplespace.rb	(revision 18273)
+++ mvm/lib/rinda/tuplespace.rb	(revision 18274)
@@ -2,6 +2,8 @@
 require 'thread'
 require 'drb/drb'
 require 'rinda/rinda'
+require 'enumerator'
+require 'forwardable'
 
 module Rinda
 
@@ -286,45 +288,70 @@
   # of Tuplespace.
 
   class TupleBag
+    class TupleBin
+      extend Forwardable
+      def_delegators '@bin', :find_all, :delete_if, :each, :empty?
 
+      def initialize
+        @bin = []
+      end
+      
+      def add(tuple)
+        @bin.push(tuple)
+      end
+      
+      def delete(tuple)
+        idx = @bin.rindex(tuple)
+        @bin.delete_at(idx) if idx
+      end
+      
+      def find(&blk)
+        @bin.reverse_each do |x|
+          return x if yield(x)
+        end
+        nil
+      end
+    end
+
     def initialize # :nodoc:
       @hash = {}
+      @enum = Enumerable::Enumerator.new(self, :each_entry)
     end
 
     ##
     # +true+ if the TupleBag to see if it has any expired entries.
 
     def has_expires?
-      @hash.each do |k, v|
-        v.each do |tuple|
-          return true if tuple.expires
-        end
+      @enum.find do |tuple|
+        tuple.expires
       end
-      false
     end
 
     ##
-    # Add +ary+ to the TupleBag.
+    # Add +tuple+ to the TupleBag.
 
-    def push(ary)
-      size = ary.size
-      @hash[size] ||= []
-      @hash[size].push(ary)
+    def push(tuple)
+      key = bin_key(tuple)
+      @hash[key] ||= TupleBin.new
+      @hash[key].add(tuple)
     end
 
     ##
-    # Removes +ary+ from the TupleBag.
+    # Removes +tuple+ from the TupleBag.
 
-    def delete(ary)
-      size = ary.size
-      @hash.fetch(size, []).delete(ary)
+    def delete(tuple)
+      key = bin_key(tuple)
+      bin = @hash[key]
+      return nil unless bin
+      bin.delete(tuple)
+      @hash.delete(key) if bin.empty?
+      tuple
     end
 
     ##
     # Finds all live tuples that match +template+.
-
     def find_all(template)
-      @hash.fetch(template.size, []).find_all do |tuple|
+      bin_for_find(template).find_all do |tuple|
         tuple.alive? && template.match(tuple)
       end
     end
@@ -333,7 +360,7 @@
     # Finds a live tuple that matches +template+.
 
     def find(template)
-      @hash.fetch(template.size, []).find do |tuple|
+      bin_for_find(template).find do |tuple|
         tuple.alive? && template.match(tuple)
       end
     end
@@ -343,7 +370,7 @@
     # +tuple+ and are alive.
 
     def find_all_template(tuple)
-      @hash.fetch(tuple.size, []).find_all do |template|
+      @enum.find_all do |template|
         template.alive? && template.match(tuple)
       end
     end
@@ -354,20 +381,39 @@
 
     def delete_unless_alive
       deleted = []
-      @hash.keys.each do |size|
-        ary = []
-        @hash[size].each do |tuple|
+      @hash.each do |key, bin|
+        bin.delete_if do |tuple|
           if tuple.alive?
-            ary.push(tuple)
+            false
           else
             deleted.push(tuple)
+            true
           end
         end
-        @hash[size] = ary
       end
       deleted
     end
 
+    private
+    def each_entry(&blk)
+      @hash.each do |k, v|
+        v.each(&blk)
+      end
+    end
+
+    def bin_key(tuple)
+      head = tuple[0]
+      if head.class == Symbol
+        return head
+      else
+        false
+      end
+    end
+
+    def bin_for_find(template)
+      key = bin_key(template)
+      key ? @hash.fetch(key, []) : @enum
+    end
   end
 
   ##
@@ -403,8 +449,7 @@
     # Adds +tuple+
 
     def write(tuple, sec=nil)
-      entry = TupleEntry.new(tuple, sec)
-      start_keeper
+      entry = create_entry(tuple, sec)
       synchronize do
         if entry.expired?
           @read_waiter.find_all_template(entry).each do |template|
@@ -414,6 +459,7 @@
           notify_event('delete', entry.value)
         else
           @bag.push(entry)
+          start_keeper if entry.expires
           @read_waiter.find_all_template(entry).each do |template|
             template.read(tuple)
           end
@@ -439,7 +485,6 @@
     def move(port, tuple, sec=nil)
       template = WaitTemplateEntry.new(self, tuple, sec)
       yield(template) if block_given?
-      start_keeper
       synchronize do
         entry = @bag.find(template)
         if entry
@@ -452,6 +497,7 @@
 
         begin
           @take_waiter.push(template)
+          start_keeper if template.expires
           while true
             raise RequestCanceledError if template.canceled?
             raise RequestExpiredError if template.expired?
@@ -476,7 +522,6 @@
     def read(tuple, sec=nil)
       template = WaitTemplateEntry.new(self, tuple, sec)
       yield(template) if block_given?
-      start_keeper
       synchronize do
         entry = @bag.find(template)
         return entry.value if entry
@@ -484,6 +529,7 @@
 
         begin
           @read_waiter.push(template)
+          start_keeper if template.expires
           template.wait
           raise RequestCanceledError if template.canceled?
           raise RequestExpiredError if template.expired?
@@ -529,6 +575,10 @@
 
     private
 
+    def create_entry(tuple, sec)
+      TupleEntry.new(tuple, sec)
+    end
+
     ##
     # Removes dead tuples.
 
@@ -566,9 +616,12 @@
     def start_keeper
       return if @keeper && @keeper.alive?
       @keeper = Thread.new do
-        while need_keeper?
-          keep_clean
+        while true
           sleep(@period)
+          synchronize do
+            break unless need_keeper?
+            keep_clean
+          end
         end
       end
     end
Index: mvm/proc.c
===================================================================
--- mvm/proc.c	(revision 18273)
+++ mvm/proc.c	(revision 18274)
@@ -531,7 +531,7 @@
     }
 
     return vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
-			  argc, argv, &pass_proc->block);
+			  argc, argv, (pass_proc ? &pass_proc->block : 0));
 }
 
 /*
Index: mvm/thread.c
===================================================================
--- mvm/thread.c	(revision 18273)
+++ mvm/thread.c	(revision 18274)
@@ -59,7 +59,6 @@
 struct timeval rb_time_interval(VALUE);
 static int rb_thread_dead(rb_thread_t *th);
 
-static void rb_mutex_unlock_all(VALUE);
 static void rb_check_deadlock(rb_vm_t *vm);
 
 void rb_signal_exec(rb_thread_t *th, int sig);
@@ -272,6 +271,17 @@
     return ST_CONTINUE;
 }
 
+typedef struct rb_mutex_struct
+{
+    rb_thread_lock_t lock;
+    rb_thread_cond_t cond;
+    struct rb_thread_struct volatile *th;
+    volatile int cond_waiting, cond_notified;
+    struct rb_mutex_struct *next_mutex;
+} mutex_t;
+
+static void rb_mutex_unlock_all(mutex_t *mutex);
+
 void
 rb_thread_terminate_all(void)
 {
@@ -413,7 +423,7 @@
 	/* unlock all locking mutexes */
 	if (th->keeping_mutexes) {
 	    rb_mutex_unlock_all(th->keeping_mutexes);
-	    th->keeping_mutexes = Qfalse;
+	    th->keeping_mutexes = NULL;
 	}
 
 	/* delete self from living_threads */
@@ -950,8 +960,12 @@
 rb_thread_execute_interrupts(rb_thread_t *th)
 {
     if (th->raised_flag) return;
+
     while (th->interrupt_flag) {
 	enum rb_thread_status status = th->status;
+	int timer_interrupt = th->interrupt_flag & 0x01;
+	int finalizer_interrupt = th->interrupt_flag & 0x04;
+
 	th->status = THREAD_RUNNABLE;
 	th->interrupt_flag = 0;
 
@@ -981,10 +995,15 @@
 	}
 	th->status = status;
 
-	/* thread pass */
-	rb_thread_schedule();
+	if (finalizer_interrupt) {
+	    rb_gc_finalize_deferred();
+	}
+
+	if (timer_interrupt) {
+	    EXEC_EVENT_HOOK(th, RUBY_EVENT_SWITCH, th->cfp->self, 0, 0);
+	    rb_thread_schedule();
+	}
     }
-    EXEC_EVENT_HOOK(th, RUBY_EVENT_SWITCH, th->cfp->self, 0, 0);
 }
 
 
@@ -1956,7 +1975,7 @@
 }
 
 static int
-subst(struct timeval *rest, const struct timeval *wait)
+subtract_tv(struct timeval *rest, const struct timeval *wait)
 {
     while (rest->tv_usec < wait->tv_usec) {
 	if (rest->tv_sec <= wait->tv_sec) {
@@ -1981,10 +2000,18 @@
 #ifndef linux
     double limit = 0;
     struct timeval wait_rest;
+# if defined(__CYGWIN__) || defined(_WIN32)
+    struct timeval start_time;
+# endif
 
     if (timeout) {
-	limit = timeofday() +
-	  (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
+# if defined(__CYGWIN__) || defined(_WIN32)
+	gettimeofday(&start_time, NULL);
+	limit = (double)start_time.tv_sec + (double)start_time.tv_usec*1e-6;
+# else
+	limit = timeofday();
+# endif
+	limit += (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
 	wait_rest = *timeout;
 	timeout = &wait_rest;
     }
@@ -1999,6 +2026,7 @@
 
 #if defined(__CYGWIN__) || defined(_WIN32)
     {
+	int finish = 0;
 	/* polling duration: 100ms */
 	struct timeval wait_100ms, *wait;
 	wait_100ms.tv_sec = 0;
@@ -2016,9 +2044,19 @@
 		    if (write) *write = orig_write;
 		    if (except) *except = orig_except;
 		    wait = &wait_100ms;
-		} while (__th->interrupt_flag == 0 && (timeout == 0 || subst(timeout, &wait_100ms)));
+		    if (timeout) {
+			struct timeval elapsed;
+			gettimeofday(&elapsed, NULL);
+			subtract_tv(&elapsed, &start_time);
+			if (!subtract_tv(timeout, &elapsed)) {
+			    finish = 1;
+			    break;
+			}
+			if (cmp_tv(&wait_100ms, timeout) < 0) wait = timeout;
+		    }
+		} while (__th->interrupt_flag == 0);
 	    }, 0, 0);
-	} while (result == 0 && (timeout == 0 || subst(timeout, &wait_100ms)));
+	} while (result == 0 && !finish);
     }
 #else
     BLOCKING_REGION({
@@ -2493,31 +2531,12 @@
  *
  */
 
-typedef struct mutex_struct {
-    rb_thread_lock_t lock;
-    rb_thread_cond_t cond;
-    rb_thread_t volatile *th;
-    volatile int cond_waiting, cond_notified;
-    VALUE next_mutex;
-} mutex_t;
-
 #define GetMutexPtr(obj, tobj) \
   Data_Get_Struct(obj, mutex_t, tobj)
 
 static const char *mutex_unlock(mutex_t *mutex);
 
 static void
-mutex_mark(void *ptr)
-{
-    if (ptr) {
-	mutex_t *mutex = ptr;
-	if (mutex->th) {
-	    rb_gc_mark(mutex->th->self);
-	}
-    }
-}
-
-static void
 mutex_free(void *ptr)
 {
     if (ptr) {
@@ -2542,7 +2561,7 @@
     VALUE volatile obj;
     mutex_t *mutex;
 
-    obj = Data_Make_Struct(klass, mutex_t, mutex_mark, mutex_free, mutex);
+    obj = Data_Make_Struct(klass, mutex_t, NULL, mutex_free, mutex);
     native_mutex_initialize(&mutex->lock);
     native_cond_initialize(&mutex->cond);
     return obj;
@@ -2583,12 +2602,13 @@
 static void
 mutex_locked(rb_thread_t *th, VALUE self)
 {
+    mutex_t *mutex;
+    GetMutexPtr(self, mutex);
+
     if (th->keeping_mutexes) {
-	mutex_t *mutex;
-	GetMutexPtr(self, mutex);
 	mutex->next_mutex = th->keeping_mutexes;
     }
-    th->keeping_mutexes = self;
+    th->keeping_mutexes = mutex;
 }
 
 /*
@@ -2754,14 +2774,14 @@
     native_mutex_unlock(&mutex->lock);
 
     if (!err) {
-	GetMutexPtr(th->keeping_mutexes, th_mutex);
+	th_mutex = th->keeping_mutexes;
 	if (th_mutex == mutex) {
 	    th->keeping_mutexes = mutex->next_mutex;
 	}
 	else {
 	    while (1) {
 		mutex_t *tmp_mutex;
-		GetMutexPtr(th_mutex->next_mutex, tmp_mutex);
+		tmp_mutex = th_mutex->next_mutex;
 		if (tmp_mutex == mutex) {
 		    th_mutex->next_mutex = tmp_mutex->next_mutex;
 		    break;
@@ -2769,7 +2789,7 @@
 		th_mutex = tmp_mutex;
 	    }
 	}
-	mutex->next_mutex = Qfalse;
+	mutex->next_mutex = NULL;
     }
 
     return err;
@@ -2796,13 +2816,13 @@
 }
 
 static void
-rb_mutex_unlock_all(VALUE mutexes)
+rb_mutex_unlock_all(mutex_t *mutexes)
 {
     const char *err;
     mutex_t *mutex;
 
     while (mutexes) {
-	GetMutexPtr(mutexes, mutex);
+	mutex = mutexes;
 	rb_warn("mutex #<%s:%p> remains to be locked by terminated thread",
 		rb_obj_classname(mutexes), (void*)mutexes);
 	mutexes = mutex->next_mutex;
Index: mvm/dir.c
===================================================================
--- mvm/dir.c	(revision 18273)
+++ mvm/dir.c	(revision 18274)
@@ -96,8 +96,7 @@
     const char *p1end, *p2end;
     int c1, c2;
 
-    if (!*p1) return *p1;
-    if (!*p2) return -*p2;
+    if (!*p1 || !*p2) return !!*p1 - !!*p2;
     p1end = p1 + strlen(p1);
     p2end = p2 + strlen(p2);
     c1 = rb_enc_codepoint(p1, p1end, enc);
@@ -295,17 +294,21 @@
 
 struct dir_data {
     DIR *dir;
-    char *path;
-    rb_encoding *intenc;
+    VALUE path;
     rb_encoding *extenc;
 };
 
 static void
+mark_dir(struct dir_data *dir)
+{
+    rb_gc_mark(dir->path);
+}
+
+static void
 free_dir(struct dir_data *dir)
 {
     if (dir) {
 	if (dir->dir) closedir(dir->dir);
-	if (dir->path) xfree(dir->path);
     }
     xfree(dir);
 }
@@ -316,11 +319,10 @@
 dir_s_alloc(VALUE klass)
 {
     struct dir_data *dirp;
-    VALUE obj = Data_Make_Struct(klass, struct dir_data, 0, free_dir, dirp);
+    VALUE obj = Data_Make_Struct(klass, struct dir_data, mark_dir, free_dir, dirp);
 
     dirp->dir = NULL;
-    dirp->path = NULL;
-    dirp->intenc = NULL;
+    dirp->path = Qnil;
     dirp->extenc = NULL;
 
     return obj;
@@ -337,66 +339,36 @@
 {
     struct dir_data *dp;
     static rb_encoding *fs_encoding;
-    rb_encoding  *intencoding, *extencoding;
+    rb_encoding  *extencoding;
     VALUE dirname, opt;
-    static VALUE sym_intenc, sym_extenc;
+    static VALUE sym_extenc;
 
-    if (!sym_intenc) {
-	sym_intenc = ID2SYM(rb_intern("internal_encoding"));
+    if (!sym_extenc) {
 	sym_extenc = ID2SYM(rb_intern("external_encoding"));
 	fs_encoding = rb_filesystem_encoding();
     }
 
-    intencoding = NULL;
     extencoding = fs_encoding;
     rb_scan_args(argc, argv, "11", &dirname, &opt);
 
     if (!NIL_P(opt)) {
-        VALUE v, extenc=Qnil, intenc=Qnil;
+        VALUE v, extenc=Qnil;
         opt = rb_convert_type(opt, T_HASH, "Hash", "to_hash");
 
-        v = rb_hash_aref(opt, sym_intenc);
-        if (!NIL_P(v)) intenc = v;
         v = rb_hash_aref(opt, sym_extenc);
         if (!NIL_P(v)) extenc = v;
 
 	if (!NIL_P(extenc)) {
 	    extencoding = rb_to_encoding(extenc);
-	    if (!NIL_P(intenc)) {
-		intencoding = rb_to_encoding(intenc);
-		if (extencoding == intencoding) {
-		    rb_warn("Ignoring internal encoding '%s': it is identical to external encoding '%s'",
-			    RSTRING_PTR(rb_inspect(intenc)),
-			    RSTRING_PTR(rb_inspect(extenc)));
-		    intencoding = NULL;
-		}
-	    }
 	}
-	else if (!NIL_P(intenc)) {
-	    rb_raise(rb_eArgError, "External encoding must be specified when internal encoding is given");
-	}
     }
 
     FilePathValue(dirname);
-    {
-	rb_encoding  *dirname_encoding = rb_enc_get(dirname);
-	if (rb_usascii_encoding() != dirname_encoding
-	    && rb_ascii8bit_encoding() != dirname_encoding
-#if defined __APPLE__
-	    && rb_utf8_encoding() != dirname_encoding
-#endif
-	    && extencoding != dirname_encoding) {
-	    if (!intencoding) intencoding = dirname_encoding;
-	    dirname = rb_str_transcode(dirname, rb_enc_from_encoding(extencoding));
-	}
-    }
 
     Data_Get_Struct(dir, struct dir_data, dp);
     if (dp->dir) closedir(dp->dir);
-    if (dp->path) xfree(dp->path);
     dp->dir = NULL;
-    dp->path = NULL;
-    dp->intenc = intencoding;
+    dp->path = Qnil;
     dp->extenc = extencoding;
     dp->dir = opendir(RSTRING_PTR(dirname));
     if (dp->dir == NULL) {
@@ -408,7 +380,7 @@
 	    rb_sys_fail(RSTRING_PTR(dirname));
 	}
     }
-    dp->path = strdup(RSTRING_PTR(dirname));
+    dp->path = rb_str_dup_frozen(dirname);
 
     return dir;
 }
@@ -428,7 +400,7 @@
 dir_s_open(int argc, VALUE *argv, VALUE klass)
 {
     struct dir_data *dp;
-    VALUE dir = Data_Make_Struct(klass, struct dir_data, 0, free_dir, dp);
+    VALUE dir = Data_Make_Struct(klass, struct dir_data, mark_dir, free_dir, dp);
 
     dir_initialize(argc, argv, dir);
     if (rb_block_given_p()) {
@@ -462,9 +434,6 @@
 dir_enc_str(VALUE str, struct dir_data *dirp)
 {
     rb_enc_associate(str, dirp->extenc);
-    if (dirp->intenc) {
-        str = rb_str_transcode(str, rb_enc_from_encoding(dirp->intenc));
-    }
     return str;
 }
 
@@ -480,9 +449,9 @@
     struct dir_data *dirp;
 
     Data_Get_Struct(dir, struct dir_data, dirp);
-    if (dirp->path) {
+    if (!NIL_P(dirp->path)) {
 	const char *c = rb_obj_classname(dir);
-	return rb_sprintf("#<%s:%s>", c, dirp->path);
+	return rb_sprintf("#<%s:%s>", c, RSTRING_PTR(dirp->path));
     }
     return rb_funcall(dir, rb_intern("to_s"), 0, 0);
 }
@@ -502,8 +471,8 @@
     struct dir_data *dirp;
 
     Data_Get_Struct(dir, struct dir_data, dirp);
-    if (!dirp->path) return Qnil;
-    return dir_enc_str(rb_str_new2(dirp->path), dirp);
+    if (NIL_P(dirp->path)) return Qnil;
+    return rb_str_dup(dirp->path);
 }
 
 /*
Index: mvm/win32/win32.c
===================================================================
--- mvm/win32/win32.c	(revision 18273)
+++ mvm/win32/win32.c	(revision 18274)
@@ -916,6 +916,12 @@
     return rb_w32_spawn(mode, rb_w32_join_argv(cmd, argv), prog);
 }
 
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#else
+# define MAXPATHLEN 512
+#endif
+
 static struct ChildRecord *
 CreateChild(const char *cmd, const char *prog, SECURITY_ATTRIBUTES *psa,
 	    HANDLE hInput, HANDLE hOutput, HANDLE hError)
@@ -928,6 +934,7 @@
     const char *shell;
     struct ChildRecord *child;
     char *p = NULL;
+    char fbuf[MAXPATHLEN];
 
     if (!cmd && !prog) {
 	errno = EFAULT;
@@ -975,7 +982,7 @@
     dwCreationFlags = (NORMAL_PRIORITY_CLASS);
 
     if (prog) {
-	if (!(p = dln_find_exe(prog, NULL))) {
+	if (!(p = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf)))) {
 	    shell = prog;
 	}
     }
@@ -1014,7 +1021,7 @@
 	    prog = cmd;
 	    for (;;) {
 		if (!*prog) {
-		    p = dln_find_exe(cmd, NULL);
+		    p = dln_find_exe_r(cmd, NULL, fbuf, sizeof(fbuf));
 		    break;
 		}
 		if (strchr(".:*?\"/\\", *prog)) {
@@ -1031,7 +1038,7 @@
 		    p = ALLOCA_N(char, len + 1);
 		    memcpy(p, cmd, len);
 		    p[len] = 0;
-		    p = dln_find_exe(p, NULL);
+		    p = dln_find_exe_r(p, NULL, fbuf, sizeof(fbuf));
 		    break;
 		}
 		prog++;
@@ -1106,13 +1113,7 @@
     return 0;
 }
 
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#else
-# define MAXPATHLEN 512
-#endif
 
-
 static NtCmdLineElement **
 cmdglob(NtCmdLineElement *patt, NtCmdLineElement **tail)
 {
@@ -2142,7 +2143,7 @@
 }
 
 static inline int
-subst(struct timeval *rest, const struct timeval *wait)
+subtract(struct timeval *rest, const struct timeval *wait)
 {
     while (rest->tv_usec < wait->tv_usec) {
 	if (rest->tv_sec <= wait->tv_sec) {
@@ -2173,7 +2174,7 @@
 #undef Sleep
 int WSAAPI
 rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
-	       struct timeval *timeout)
+	      struct timeval *timeout)
 {
     int r;
     fd_set pipe_rd;
@@ -2182,11 +2183,29 @@
     fd_set else_wr;
     fd_set except;
     int nonsock = 0;
+    struct timeval limit;
 
     if (nfds < 0 || (timeout && (timeout->tv_sec < 0 || timeout->tv_usec < 0))) {
 	errno = EINVAL;
 	return -1;
     }
+
+    if (timeout) {
+	if (timeout->tv_sec < 0 ||
+	    timeout->tv_usec < 0 ||
+	    timeout->tv_usec >= 1000000) {
+	    errno = EINVAL;
+	    return -1;
+	}
+	gettimeofday(&limit, NULL);
+	limit.tv_sec += timeout->tv_sec;
+	limit.tv_usec += timeout->tv_usec;
+	if (limit.tv_usec >= 1000000) {
+	    limit.tv_usec -= 1000000;
+	    limit.tv_sec++;
+	}
+    }
+
     if (!NtSocketsInitialized) {
 	StartSockets();
     }
@@ -2222,10 +2241,9 @@
 	struct timeval rest;
 	struct timeval wait;
 	struct timeval zero;
-	if (timeout) rest = *timeout;
 	wait.tv_sec = 0; wait.tv_usec = 10 * 1000; // 10ms
 	zero.tv_sec = 0; zero.tv_usec = 0;         //  0ms
-	do {
+	for (;;) {
 	    if (nonsock) {
 		// modifying {else,pipe,cons}_rd is safe because
 		// if they are modified, function returns immediately.
@@ -2241,8 +2259,7 @@
 		break;
 	    }
 	    else {
-		struct timeval *dowait =
-		    compare(&rest, &wait) < 0 ? &rest : &wait;
+		struct timeval *dowait = &wait;
 
 		fd_set orig_rd;
 		fd_set orig_wr;
@@ -2256,10 +2273,16 @@
 		if (wr) *wr = orig_wr;
 		if (ex) *ex = orig_ex;
 
-		// XXX: should check the time select spent
+		if (timeout) {
+		    struct timeval now;
+		    gettimeofday(&now, NULL);
+		    rest = limit;
+		    if (!subtract(&rest, &now)) break;
+		    if (compare(&rest, &wait) < 0) dowait = &rest;
+		}
 		Sleep(dowait->tv_sec * 1000 + dowait->tv_usec / 1000);
 	    }
-	} while (!timeout || subst(&rest, &wait));
+	}
     }
 
     return r;
@@ -2431,7 +2454,8 @@
     int r;
     int ret;
     int mode;
-    int flg;
+    st_data_t data;
+    DWORD flg;
     WSAOVERLAPPED wol;
     WSABUF wbuf;
     int err;
@@ -2441,7 +2465,8 @@
 	StartSockets();
 
     s = TO_SOCKET(fd);
-    st_lookup(socklist, (st_data_t)s, (st_data_t *)&mode);
+    st_lookup(socklist, (st_data_t)s, &data);
+    mode = (int)data;
     if (!cancel_io || (mode & O_NONBLOCK)) {
 	RUBY_CRITICAL({
 	    if (input) {
@@ -2919,6 +2944,7 @@
     int arg;
     int ret;
     int flag = 0;
+    st_data_t data;
     u_long ioctlArg;
 
     if (!is_socket(sock)) {
@@ -2933,7 +2959,8 @@
     va_start(va, cmd);
     arg = va_arg(va, int);
     va_end(va);
-    st_lookup(socklist, (st_data_t)sock, (st_data_t*)&flag);
+    st_lookup(socklist, (st_data_t)sock, &data);
+    flag = (int)data;
     if (arg & O_NONBLOCK) {
 	flag |= O_NONBLOCK;
 	ioctlArg = 1;
@@ -3583,7 +3610,7 @@
     HANDLE h;
     int ret;
     if (IsWin95()) {
-	int fd = open(path, O_WRONLY), e;
+	int fd = open(path, O_WRONLY), e = 0;
 	if (fd == -1) return -1;
 	ret = chsize(fd, (unsigned long)length);
 	if (ret == -1) e = errno;
@@ -3985,13 +4012,16 @@
 {
     SOCKET sock = TO_SOCKET(fd);
     int save_errno = errno;
+    st_data_t key;
 
     if (!is_socket(sock)) {
 	UnlockFile((HANDLE)sock, 0, 0, LK_LEN, LK_LEN);
 	return _close(fd);
     }
     _set_osfhnd(fd, (SOCKET)INVALID_HANDLE_VALUE);
-    st_delete(socklist, (st_data_t *)&sock, NULL);
+    key = (st_data_t)sock;
+    st_delete(socklist, &key, NULL);
+    sock = (SOCKET)key;
     _close(fd);
     errno = save_errno;
     if (closesocket(sock) == SOCKET_ERROR) {
Index: mvm/gc.c
===================================================================
--- mvm/gc.c	(revision 18273)
+++ mvm/gc.c	(revision 18274)
@@ -574,7 +574,6 @@
 	    objs--;
 	}
     }
-    	
 
     lo = 0;
     hi = heaps_used;
@@ -1078,7 +1077,7 @@
 	rb_mark_generic_ivar(ptr);
     }
 
-    switch (obj->as.basic.flags & T_MASK) {
+    switch (BUILTIN_TYPE(obj)) {
       case T_NIL:
       case T_FIXNUM:
 	rb_bug("rb_gc_mark() called for broken object");
@@ -1221,7 +1220,7 @@
     }
 
     gc_mark(objspace, obj->as.basic.klass, lev);
-    switch (obj->as.basic.flags & T_MASK) {
+    switch (BUILTIN_TYPE(obj)) {
       case T_ICLASS:
       case T_CLASS:
       case T_MODULE:
@@ -1315,13 +1314,22 @@
 
       default:
 	rb_bug("rb_gc_mark(): unknown data type 0x%lx(%p) %s",
-	       obj->as.basic.flags & T_MASK, obj,
+	       BUILTIN_TYPE(obj), obj,
 	       is_pointer_to_heap(objspace, obj) ? "corrupted object" : "non object");
     }
 }
 
-static void obj_free(rb_objspace_t *, VALUE);
+static int obj_free(rb_objspace_t *, VALUE);
 
+static inline void
+add_freelist(rb_objspace_t *objspace, RVALUE *p)
+{
+    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
+    p->as.free.flags = 0;
+    p->as.free.next = freelist;
+    freelist = p;
+}
+
 static void
 finalize_list(rb_objspace_t *objspace, RVALUE *p)
 {
@@ -1329,11 +1337,12 @@
 	RVALUE *tmp = p->as.free.next;
 	run_final(objspace, (VALUE)p);
 	if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
-            VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-	    p->as.free.flags = 0;
-	    p->as.free.next = freelist;
-	    freelist = p;
+	    add_freelist(objspace, p);
 	}
+	else {
+	    struct heaps_slot *slot = (struct heaps_slot *)RDATA(p)->dmark;
+	    slot->limit--;
+	}
 	p = tmp;
     }
 }
@@ -1382,6 +1391,7 @@
 
     do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65;
     free_min = (heaps_used * HEAP_OBJ_LIMIT)  * 0.2;
+
     if (free_min < FREE_MIN) {
 	do_heap_free = heaps_used * HEAP_OBJ_LIMIT;
         free_min = FREE_MIN;
@@ -1394,27 +1404,28 @@
 	int n = 0;
 	RVALUE *free = freelist;
 	RVALUE *final = final_list;
+	int deferred;
 
 	p = heaps[i].slot; pend = p + heaps[i].limit;
 	while (p < pend) {
 	    if (!(p->as.basic.flags & FL_MARK)) {
-		if (p->as.basic.flags) {
-		    obj_free(objspace, (VALUE)p);
-		}
-		if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
-		    p->as.free.flags = FL_MARK; /* remain marked */
+		if (p->as.basic.flags &&
+		    ((deferred = obj_free(objspace, (VALUE)p)) ||
+		     ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) {
+		    if (!deferred) {
+			p->as.free.flags = T_DEFERRED;
+			RDATA(p)->dfree = 0;
+		    }
+		    p->as.free.flags |= FL_MARK;
 		    p->as.free.next = final_list;
 		    final_list = p;
 		}
 		else {
-                    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-		    p->as.free.flags = 0;
-		    p->as.free.next = freelist;
-		    freelist = p;
+		    add_freelist(objspace, p);
 		}
 		n++;
 	    }
-	    else if (RBASIC(p)->flags == FL_MARK) {
+	    else if (BUILTIN_TYPE(p) == T_DEFERRED) {
 		/* objects to be finalized */
 		/* do nothing remain marked */
 	    }
@@ -1426,11 +1437,15 @@
 	}
 	if (n == heaps[i].limit && freed > do_heap_free) {
 	    RVALUE *pp;
+	    int f_count = 0;
 
-	    heaps[i].limit = 0;
 	    for (pp = final_list; pp != final; pp = pp->as.free.next) {
-		p->as.free.flags |= FL_SINGLETON; /* freeing page mark */
+		f_count++;
+		RDATA(pp)->dmark = (void *)&heaps[i];
+		pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */
 	    }
+	    heaps[i].limit = f_count;
+
 	    freelist = free;	/* cancel this page from freelist */
 	}
 	else {
@@ -1451,25 +1466,24 @@
     /* clear finalization list */
     if (final_list) {
 	deferred_final_list = final_list;
-	return;
+	RUBY_VM_SET_FINALIZER_INTERRUPT(GET_THREAD());
     }
-    free_unused_heaps(objspace);
+    else{
+	free_unused_heaps(objspace);
+    }
 }
 
 void
 rb_gc_force_recycle(VALUE p)
 {
     rb_objspace_t *objspace = &rb_objspace;
-    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-    RANY(p)->as.free.flags = 0;
-    RANY(p)->as.free.next = freelist;
-    freelist = RANY(p);
+    add_freelist(objspace, (RVALUE *)p);
 }
 
-static void
+static int
 obj_free(rb_objspace_t *objspace, VALUE obj)
 {
-    switch (RANY(obj)->as.basic.flags & T_MASK) {
+    switch (BUILTIN_TYPE(obj)) {
       case T_NIL:
       case T_FIXNUM:
       case T_TRUE:
@@ -1482,7 +1496,7 @@
 	rb_free_generic_ivar((VALUE)obj);
     }
 
-    switch (RANY(obj)->as.basic.flags & T_MASK) {
+    switch (BUILTIN_TYPE(obj)) {
       case T_OBJECT:
 	if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) &&
             RANY(obj)->as.object.as.heap.ivptr) {
@@ -1523,7 +1537,14 @@
 		xfree(DATA_PTR(obj));
 	    }
 	    else if (RANY(obj)->as.data.dfree) {
-		(*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
+		if (1) {
+		    RANY(obj)->as.basic.flags &= ~T_MASK;
+		    RANY(obj)->as.basic.flags |= T_DEFERRED;
+		    return 1;
+		}
+		else {
+		    (*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
+		}
 	    }
 	}
 	break;
@@ -1538,7 +1559,17 @@
 	break;
       case T_FILE:
 	if (RANY(obj)->as.file.fptr) {
-	    rb_io_fptr_finalize(RANY(obj)->as.file.fptr);
+	    rb_io_t *fptr = RANY(obj)->as.file.fptr;
+	    if (1) {
+		RANY(obj)->as.basic.flags &= ~T_MASK;
+		RANY(obj)->as.basic.flags |= T_DEFERRED;
+		RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize;
+		RDATA(obj)->data = fptr;
+		return 1;
+	    }
+	    else {
+		rb_io_fptr_finalize(fptr);
+	    }
 	}
 	break;
       case T_RATIONAL:
@@ -1567,7 +1598,7 @@
 	    xfree(RANY(obj)->as.node.u1.node);
 	    break;
 	}
-	return;			/* no need to free iv_tbl */
+	break;			/* no need to free iv_tbl */
 
       case T_STRUCT:
 	if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
@@ -1578,8 +1609,10 @@
 
       default:
 	rb_bug("gc_sweep(): unknown data type 0x%lx(%p)",
-	       RANY(obj)->as.basic.flags & T_MASK, (void*)obj);
+	       BUILTIN_TYPE(obj), (void*)obj);
     }
+
+    return 0;
 }
 
 #ifdef __GNUC__
@@ -1848,6 +1881,7 @@
 		  case T_NONE:
 		  case T_ICLASS:
 		  case T_NODE:
+		  case T_DEFERRED:
 		    continue;
 		  case T_CLASS:
 		    if (FL_TEST(p, FL_SINGLETON)) continue;
@@ -1998,14 +2032,19 @@
 run_final(rb_objspace_t *objspace, VALUE obj)
 {
     long i;
-    int status, critical_save = rb_thread_critical;
+    int status;
     VALUE args[3], table, objid;
 
     objid = rb_obj_id(obj);	/* make obj into id */
-    rb_thread_critical = Qtrue;
-    args[1] = 0;
-    args[2] = (VALUE)rb_safe_level();
-    if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) {
+
+    if (RDATA(obj)->dfree) {
+	(*RDATA(obj)->dfree)(DATA_PTR(obj));
+    }
+
+    if (finalizer_table &&
+	st_delete(finalizer_table, (st_data_t*)&obj, &table)) {
+	args[1] = 0;
+	args[2] = (VALUE)rb_safe_level();
 	if (!args[1] && RARRAY_LEN(table) > 0) {
 	    args[1] = rb_obj_freeze(rb_ary_new3(1, objid));
 	}
@@ -2016,15 +2055,14 @@
 	    rb_protect(run_single_final, (VALUE)args, &status);
 	}
     }
-    rb_thread_critical = critical_save;
 }
 
 static void
 gc_finalize_deferred(rb_objspace_t *objspace)
 {
     RVALUE *p = deferred_final_list;
+    deferred_final_list = 0;
 
-    deferred_final_list = 0;
     if (p) {
 	finalize_list(objspace, p);
     }
@@ -2042,7 +2080,10 @@
 {
     RVALUE *p = (RVALUE *)key, **final_list = (RVALUE **)arg;
     if (p->as.basic.flags & FL_FINALIZE) {
-	p->as.free.flags = FL_MARK; /* remain marked */
+	if (BUILTIN_TYPE(p) != T_DEFERRED) {
+	    p->as.free.flags = FL_MARK | T_DEFERRED; /* remain marked */
+	    RDATA(p)->dfree = 0;
+	}
 	p->as.free.next = *final_list;
 	*final_list = p;
     }
@@ -2322,6 +2363,7 @@
 	    COUNT_TYPE(T_UNDEF);
 	    COUNT_TYPE(T_NODE);
 	    COUNT_TYPE(T_ICLASS);
+	    COUNT_TYPE(T_DEFERRED);
 #undef COUNT_TYPE
           default:              type = INT2NUM(i); break;
         }
Index: mvm/regint.h
===================================================================
--- mvm/regint.h	(revision 18273)
+++ mvm/regint.h	(revision 18274)
@@ -85,6 +85,10 @@
 /* escape other system UChar definition */
 #ifndef RUBY_DEFINES_H
 #include "ruby/ruby.h"
+#undef xmalloc
+#undef xrealloc
+#undef xcalloc
+#undef xfree
 #endif
 #ifdef ONIG_ESCAPE_UCHAR_COLLISION
 #undef ONIG_ESCAPE_UCHAR_COLLISION
Index: mvm/parse.y
===================================================================
--- mvm/parse.y	(revision 18273)
+++ mvm/parse.y	(revision 18274)
@@ -155,9 +155,7 @@
         if (tbl->tbl) {
             xfree(tbl->tbl);
         }
-        if (tbl) {
-            xfree(tbl);
-        }
+        xfree(tbl);
     }
 }
 
Index: mvm/dln.c
===================================================================
--- mvm/dln.c	(revision 18273)
+++ mvm/dln.c	(revision 18274)
@@ -348,14 +348,14 @@
 static int
 dln_init(const char *prog)
 {
-    char *file;
+    char *file, fbuf[MAXPATHLEN];
     int fd;
     struct exec hdr;
     struct nlist *syms;
 
     if (dln_init_p == 1) return 0;
 
-    file = dln_find_exe(prog, NULL);
+    file = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf));
     if (file == NULL || (fd = open(file, O_RDONLY)) < 0) {
 	dln_errno = errno;
 	return -1;
@@ -911,7 +911,7 @@
 static int
 load_lib(const char *lib)
 {
-    char *path, *file;
+    char *path, *file, fbuf[MAXPATHLEN];
     char armagic[SARMAG];
     int fd, size;
     struct ar_hdr ahdr;
@@ -942,7 +942,7 @@
     path = getenv("DLN_LIBRARY_PATH");
     if (path == NULL) path = dln_librrb_ary_path;
 
-    file = dln_find_file(lib, path);
+    file = dln_find_file_r(lib, path, fbuf, sizeof(fbuf));
     fd = open(file, O_RDONLY);
     if (fd == -1) goto syserr;
     size = read(fd, armagic, SARMAG);
Index: mvm/ext/bigdecimal/bigdecimal.c
===================================================================
--- mvm/ext/bigdecimal/bigdecimal.c	(revision 18273)
+++ mvm/ext/bigdecimal/bigdecimal.c	(revision 18274)
@@ -1844,7 +1844,7 @@
 
     /* 
      * 0x01: Determines what happens when the result of a computation is an
-     * underflow (a result too large to be represented). See BigDecimal.mode.
+     * overflow (a result too large to be represented). See BigDecimal.mode.
      */
     rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW",INT2FIX(VP_EXCEPTION_OVERFLOW));
 
Index: mvm/ext/win32ole/sample/ienavi2.rb
===================================================================
--- mvm/ext/win32ole/sample/ienavi2.rb	(revision 0)
+++ mvm/ext/win32ole/sample/ienavi2.rb	(revision 18274)
@@ -0,0 +1,40 @@
+require 'win32ole'
+
+class IEHandler
+  attr_reader :loop
+  def initialize
+    @urls = []
+    @loop = true
+  end
+  def method_missing(event, *args)
+    case event
+    when "BeforeNavigate2"
+      puts "Now Navigate #{args[1]}..."
+    end
+  end
+  def onNavigateComplete2(pdisp, url)
+    @urls << url
+  end
+  def onOnQuit
+    puts "Now Stop IE..."
+    @loop = false
+  end
+  def put_urls
+    puts "You Navigated the URLs ..."
+    @urls.each_with_index do |url, i|
+      puts "(#{i+1}) #{url}"
+    end
+  end
+end
+
+ie = WIN32OLE.new('InternetExplorer.Application')
+ie.visible = true
+ie.gohome
+
+ev = WIN32OLE_EVENT.new(ie)
+ev.handler = IEHandler.new
+
+while (ev.handler.loop)
+  WIN32OLE_EVENT.message_loop
+end
+ev.handler.put_urls

Property changes on: mvm/ext/win32ole/sample/ienavi2.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: mvm/ext/win32ole/win32ole.c
===================================================================
--- mvm/ext/win32ole/win32ole.c	(revision 18273)
+++ mvm/ext/win32ole/win32ole.c	(revision 18274)
@@ -118,7 +118,7 @@
 
 #define WC2VSTR(x) ole_wc2vstr((x), TRUE)
 
-#define WIN32OLE_VERSION "1.2.7"
+#define WIN32OLE_VERSION "1.3.0"
 
 typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
     (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
@@ -499,6 +499,8 @@
 static VALUE foleparam_inspect(VALUE self);
 static long ole_search_event_at(VALUE ary, VALUE ev);
 static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL  *is_default);
+static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler);
+static void ole_delete_event(VALUE ary, VALUE ev);
 static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
 static VALUE hash2result(VALUE hash);
 static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams);
@@ -517,7 +519,10 @@
 static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg);
 static VALUE fev_on_event(int argc, VALUE *argv, VALUE self);
 static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self);
+static VALUE fev_off_event(int argc, VALUE *argv, VALUE self);
 static VALUE fev_unadvise(VALUE self);
+static VALUE fev_set_handler(VALUE self, VALUE val);
+static VALUE fev_get_handler(VALUE self);
 static VALUE evs_push(VALUE ev);
 static VALUE evs_delete(long i);
 static VALUE evs_entry(long i);
@@ -3227,7 +3232,7 @@
     if (is_bracket) {
         DispID = DISPID_VALUE;
         argc += 1;
-        rb_funcall(paramS, rb_intern("unshift"), 1, cmd);
+	rb_ary_unshift(paramS, cmd);
     } else {
         wcmdname = ole_vstr2wc(cmd);
         hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
@@ -7432,7 +7437,34 @@
     }
     return def_event;
 }
+static VALUE
+ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler)
+{
+    VALUE mid;
 
+    *is_default_handler = FALSE;
+    mid = rb_to_id(rb_sprintf("on%s", StringValuePtr(ev)));
+    if (rb_respond_to(handler, mid)) {
+	return mid;
+    }
+    mid = rb_intern("method_missing");
+    if (rb_respond_to(handler, mid)) {
+	*is_default_handler = TRUE;
+	return mid;
+    }
+    return Qnil;
+}
+
+static void
+ole_delete_event(VALUE ary, VALUE ev)
+{
+    long at = -1;
+    at = ole_search_event_at(ary, ev);
+    if (at >= 0) {
+        rb_ary_delete_at(ary, at);
+    }
+}
+
 static void 
 hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams)
 {
@@ -7490,8 +7522,9 @@
 {
     VALUE *parg = (VALUE *)arg;
     VALUE handler = parg[0];
-    VALUE args = parg[1];
-    return rb_apply(handler, rb_intern("call"), args);
+    VALUE mid = parg[1];
+    VALUE args = parg[2];
+    return rb_apply(handler, mid, args);
 }
 
 static VALUE
@@ -7499,12 +7532,10 @@
 {
     
     VALUE e = rb_errinfo();
-    VALUE c = rb_funcall(e, rb_intern("class"), 0);
     VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0);
     VALUE msg = rb_funcall(e, rb_intern("message"), 0);
-    c = rb_funcall(c, rb_intern("to_s"), 0);
     bt = rb_ary_entry(bt, 0);
-    fprintf(stdout, "%s: %s (%s)\n", StringValuePtr(bt), StringValuePtr(msg), StringValuePtr(c));
+    fprintf(stdout, "%s: %s (%s)\n", StringValuePtr(bt), StringValuePtr(msg), rb_obj_classname(e));
     rb_backtrace();
     ruby_finalize();
     exit(-1);
@@ -7530,9 +7561,11 @@
     unsigned int i;
     ITypeInfo *pTypeInfo;
     VARIANT *pvar;
-    VALUE ary, obj, event, handler, args, outargv, ev, result;
-    VALUE arg[2];
-    VALUE is_outarg;
+    VALUE ary, obj, event, args, outargv, ev, result;
+    VALUE handler = Qnil;
+    VALUE arg[3];
+    VALUE mid;
+    VALUE is_outarg = Qfalse;
     BOOL is_default_handler = FALSE;
     int state;
 
@@ -7554,9 +7587,21 @@
     }
     ev = WC2VSTR(bstr);
     event = ole_search_event(ary, ev, &is_default_handler);
-    if (NIL_P(event)) {
-        return NOERROR;
+    if (TYPE(event) == T_ARRAY) {
+	handler = rb_ary_entry(event, 0);
+	mid = rb_intern("call");
+	is_outarg = rb_ary_entry(event, 3);
+    } else {
+	handler = rb_ivar_get(obj, rb_intern("handler"));
+	if (handler == Qnil) {
+	    return NOERROR;
+	}
+	mid = ole_search_handler_method(handler, ev, &is_default_handler);
     }
+    if (handler == Qnil || mid == Qnil) {
+	return NOERROR;
+    }
+
     args = rb_ary_new();
     if (is_default_handler) {
         rb_ary_push(args, ev);
@@ -7567,8 +7612,6 @@
         pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
         rb_ary_push(args, ole_variant2val(pvar));
     }
-    handler = rb_ary_entry(event, 0);
-    is_outarg = rb_ary_entry(event, 3);
     outargv = Qnil;
     if (is_outarg == Qtrue) {
 	outargv = rb_ary_new();
@@ -7583,7 +7626,8 @@
      * and exit ruby process by Win32OLE itself.
      */
     arg[0] = handler;
-    arg[1] = args;
+    arg[1] = mid;
+    arg[2] = args;
     result = rb_protect(exec_callback, (VALUE)arg, &state);
     if (state != 0) {
 	rescue_callback(Qnil);
@@ -8079,16 +8123,12 @@
 static void
 add_event_call_back(VALUE obj, VALUE event, VALUE data)
 {
-    long at = -1;
     VALUE events = rb_ivar_get(obj, id_events);
     if (NIL_P(events) || TYPE(events) != T_ARRAY) {
         events = rb_ary_new();
         rb_ivar_set(obj, id_events, events);
     }
-    at = ole_search_event_at(events, event);
-    if (at >= 0) {
-        rb_ary_delete_at(events, at);
-    }
+    ole_delete_event(events, event);
     rb_ary_push(events, data);
 }
 
@@ -8167,6 +8207,40 @@
 
 /*
  *  call-seq:
+ *     WIN32OLE_EVENT#off_event([event])
+ * 
+ *  removes the callback of event.
+ *
+ *    ie = WIN32OLE.new('InternetExplorer.Application')
+ *    ev = WIN32OLE_EVENT.new(ie)
+ *    ev.on_event('BeforeNavigate2') {|*args|
+ *      args.last[6] = true
+ *    }
+ *      ...
+ *    ev.off_event('BeforeNavigate2')
+ *      ...
+ */
+static VALUE
+fev_off_event(int argc, VALUE *argv, VALUE self)
+{
+    VALUE event = Qnil;
+    VALUE events;
+
+    rb_secure(4);
+    rb_scan_args(argc, argv, "01", &event);
+    if(!NIL_P(event)) {
+        Check_SafeStr(event);
+    }
+    events = rb_ivar_get(self, id_events);
+    if (NIL_P(events)) {
+	return Qnil;
+    }
+    ole_delete_event(events, event);
+    return Qnil;
+}
+
+/*
+ *  call-seq:
  *     WIN32OLE_EVENT#unadvise -> nil
  *
  *  disconnects OLE server. If this method called, then the WIN32OLE_EVENT object
@@ -8220,6 +8294,64 @@
     return rb_funcall(ary_ole_event, rb_intern("length"), 0);
 }
 
+/*
+ *  call-seq:
+ *     WIN32OLE_EVENT#handler=
+ *
+ *  sets event handler object. If handler object has onXXX
+ *  method according to XXX event, then onXXX method is called 
+ *  when XXX event occurs.
+ *  
+ *  If handler object has method_missing and there is no
+ *  method according to the event, then method_missing
+ *  called and 1-st argument is event name.
+ *
+ *  If handler object has onXXX method and there is block
+ *  defined by WIN32OLE_EVENT#on_event('XXX'){},
+ *  then block is executed but handler object method is not called
+ *  when XXX event occurs.
+ *
+ *      class Handler
+ *        def onStatusTextChange(text)
+ *          puts "StatusTextChanged"
+ *        end
+ *        def onPropertyChange(prop)
+ *          puts "PropertyChanged"
+ *        end
+ *        def method_missing(ev, *arg)
+ *          puts "other event #{ev}"
+ *        end
+ *      end
+ *      
+ *      handler = Handler.new
+ *      ie = WIN32OLE.new('InternetExplorer.Application')
+ *      ev = WIN32OLE_EVENT.new(ie)
+ *      ev.on_event("StatusTextChange") {|*args|
+ *        puts "this block executed."
+ *        puts "handler.onStatusTextChange method is not called."
+ *      }
+ *      ev.handler = handler
+ *
+ */
+static VALUE
+fev_set_handler(VALUE self, VALUE val)
+{
+    return rb_ivar_set(self, rb_intern("handler"), val);
+}
+
+/*
+ *  call-seq:
+ *     WIN32OLE_EVENT#handler
+ *
+ *  returns handler object. 
+ *  
+ */
+static VALUE
+fev_get_handler(VALUE self)
+{
+    return rb_ivar_get(self, rb_intern("handler"));
+}
+
 static void 
 olevariant_free(struct olevariantdata *pvar)
 {
@@ -8854,7 +8986,10 @@
     rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1);
     rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1);
     rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1);
+    rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1);
     rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0);
+    rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1);
+    rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0);
 
     cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
     rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
Index: mvm/dln.h
===================================================================
--- mvm/dln.h	(revision 18273)
+++ mvm/dln.h	(revision 18274)
@@ -28,8 +28,8 @@
 # define _(args) ()
 #endif
 
-char *dln_find_exe(const char*,const char*);
-char *dln_find_file(const char*,const char*);
+DEPRECATED(char *dln_find_exe(const char*,const char*));
+DEPRECATED(char *dln_find_file(const char*,const char*));
 char *dln_find_exe_r(const char*,const char*,char*,int);
 char *dln_find_file_r(const char*,const char*,char*,int);
 
Index: mvm/.merged-trunk-revision
===================================================================
--- mvm/.merged-trunk-revision	(revision 18273)
+++ mvm/.merged-trunk-revision	(revision 18274)
@@ -1 +1 @@
-18206
+18273
Index: mvm/vm.c
===================================================================
--- mvm/vm.c	(revision 18273)
+++ mvm/vm.c	(revision 18274)
@@ -508,7 +508,9 @@
 
     TH_PUSH_TAG(th);
     if ((state = EXEC_TAG()) == 0) {
-	th->safe_level = proc->safe_level;
+	if (!proc->is_from_method) {
+	    th->safe_level = proc->safe_level;
+	}
 	val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, 0);
     }
     TH_POP_TAG();
@@ -1474,7 +1476,7 @@
 	if (th->locking_mutex != Qfalse) {
 	    rb_bug("thread_free: locking_mutex must be NULL (%p:%ld)", th, th->locking_mutex);
 	}
-	if (th->keeping_mutexes != Qfalse) {
+	if (th->keeping_mutexes != NULL) {
 	    rb_bug("thread_free: keeping_mutexes must be NULL (%p:%ld)", th, th->locking_mutex);
 	}
 
Index: mvm/version.h
===================================================================
--- mvm/version.h	(revision 18273)
+++ mvm/version.h	(revision 18274)
@@ -1,7 +1,7 @@
 #define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2008-07-25"
+#define RUBY_RELEASE_DATE "2008-07-31"
 #define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20080725
+#define RUBY_RELEASE_CODE 20080731
 #define RUBY_PATCHLEVEL 0
 
 #define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
 #define RUBY_VERSION_TEENY 0
 #define RUBY_RELEASE_YEAR 2008
 #define RUBY_RELEASE_MONTH 7
-#define RUBY_RELEASE_DAY 25
+#define RUBY_RELEASE_DAY 31
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];
Index: mvm/test/ruby/test_koi8.rb
===================================================================
--- mvm/test/ruby/test_koi8.rb	(revision 18273)
+++ mvm/test/ruby/test_koi8.rb	(revision 18274)
@@ -1,22 +0,0 @@
-require "test/unit"
-
-class TestKOI8 < Test::Unit::TestCase
-  ASSERTS = %q(
-    (0xc0..0xdf).each do |c|
-      c1 = c.chr("ENCODING")
-      c2 = (c + 0x20).chr("ENCODING")
-      assert_match(/^(#{ c1 })\1$/i, c2 + c1)
-      assert_match(/^(#{ c2 })\1$/i, c1 + c2)
-      assert_match(/^[#{ c1 }]+$/i, c2 + c1)
-      assert_match(/^[#{ c2 }]+$/i, c1 + c2)
-    end
-  )
-
-  def test_koi8_r
-    eval("# encoding: koi8-r\n" + ASSERTS.gsub("ENCODING", "koi8-r"))
-  end
-
-  def test_koi8_u
-    eval("# encoding: koi8-u\n" + ASSERTS.gsub("ENCODING", "koi8-u"))
-  end
-end
Index: mvm/test/ruby/test_io_m17n.rb
===================================================================
--- mvm/test/ruby/test_io_m17n.rb	(revision 18273)
+++ mvm/test/ruby/test_io_m17n.rb	(revision 18274)
@@ -161,11 +161,13 @@
     with_tmpdir {
       src = "before \e$B\x23\x30\x23\x31\e(B after".force_encoding("iso-2022-jp")
       generate_file('tmp', src)
-      s = open("tmp", "r:iso-2022-jp:euc-jp") {|f|
-        f.gets("0".force_encoding("euc-jp"))
-      }
-      assert_equal(Encoding.find("euc-jp"), s.encoding)
-      assert_str_equal(src.encode("euc-jp"), s)
+      assert_raise(NotImplementedError) do
+        s = open("tmp", "r:iso-2022-jp:euc-jp") {|f|
+          f.gets("0".force_encoding("euc-jp"))
+        }
+        assert_equal(Encoding.find("euc-jp"), s.encoding)
+        assert_str_equal(src.encode("euc-jp"), s)
+      end
     }
   end
 
@@ -218,13 +220,30 @@
     with_tmpdir {
       src = "\e$B\x23\x30\x23\x31\e(B".force_encoding("iso-2022-jp")
       generate_file('tmp', src)
-      open("tmp", "r:iso-2022-jp:euc-jp") {|f|
-        assert_equal("\xa3\xb0".force_encoding("euc-jp"), f.getc)
-        assert_equal("\xa3\xb1".force_encoding("euc-jp"), f.getc)
-      }
+      assert_raise(NotImplementedError) do
+        open("tmp", "r:iso-2022-jp:euc-jp") {|f|
+          assert_equal("\xa3\xb0".force_encoding("euc-jp"), f.getc)
+          assert_equal("\xa3\xb1".force_encoding("euc-jp"), f.getc)
+        }
+      end
     }
   end
 
+  def test_ungetc_stateful_conversion
+    with_tmpdir {
+      src = "before \e$B\x23\x30\x23\x31\e(B after".force_encoding("iso-2022-jp")
+      generate_file('tmp', src)
+      assert_raise(NotImplementedError) do
+        s = open("tmp", "r:iso-2022-jp:euc-jp") {|f|
+          f.ungetc("0".force_encoding("euc-jp"))
+          f.read
+        }
+        assert_equal(Encoding.find("euc-jp"), s.encoding)
+        assert_str_equal(("0" + src).encode("euc-jp"), s)
+      end
+    }
+  end
+
   def test_open_ascii
     with_tmpdir {
       src = "abc\n"
Index: mvm/test/ruby/test_require.rb
===================================================================
--- mvm/test/ruby/test_require.rb	(revision 18273)
+++ mvm/test/ruby/test_require.rb	(revision 18274)
@@ -19,13 +19,20 @@
   end
 
   def test_require_too_long_filename
-    assert_in_out_err([], <<-INPUT, %w(:ok), /^.+$/)
+    assert_in_out_err([], <<-INPUT, %w(:ok), [])
       begin
         require '#{ "foo/" * 10000 }foo'
       rescue LoadError
         p :ok
       end
     INPUT
+
+    assert_in_out_err(["-S", "foo/" * 10000 + "foo"], "") do |r, e|
+      assert_equal([], r)
+      assert_operator(2, :<=, e.size)
+      assert_equal("openpath: pathname too long (ignored)", e.first)
+      assert_match(/\(LoadError\)/, e.last)
+    end
   end
 
   def test_require_path_home
Index: mvm/test/ruby/test_math.rb
===================================================================
--- mvm/test/ruby/test_math.rb	(revision 18273)
+++ mvm/test/ruby/test_math.rb	(revision 18274)
@@ -110,6 +110,7 @@
     check(0, Math.log(1, 10))
     check(1, Math.log(10, 10))
     check(2, Math.log(100, 10))
+    assert_equal(1.0/0, Math.log(1.0/0))
     assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log(0) }
     assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log(-1) }
   end
@@ -118,6 +119,7 @@
     check(0, Math.log2(1))
     check(1, Math.log2(2))
     check(2, Math.log2(4))
+    assert_equal(1.0/0, Math.log2(1.0/0))
     assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log2(0) }
     assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log2(-1) }
   end
@@ -126,6 +128,7 @@
     check(0, Math.log10(1))
     check(1, Math.log10(10))
     check(2, Math.log10(100))
+    assert_equal(1.0/0, Math.log10(1.0/0))
     assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log10(0) }
     assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log10(-1) }
   end
@@ -134,6 +137,7 @@
     check(0, Math.sqrt(0))
     check(1, Math.sqrt(1))
     check(2, Math.sqrt(4))
+    assert_equal(1.0/0, Math.sqrt(1.0/0))
     assert_raise(Errno::EDOM, Errno::ERANGE) { Math.sqrt(-1) }
   end
 
Index: mvm/test/ruby/enc/test_koi8.rb
===================================================================
--- mvm/test/ruby/enc/test_koi8.rb	(revision 0)
+++ mvm/test/ruby/enc/test_koi8.rb	(revision 18274)
@@ -0,0 +1,22 @@
+require "test/unit"
+
+class TestKOI8 < Test::Unit::TestCase
+  ASSERTS = %q(
+    (0xc0..0xdf).each do |c|
+      c1 = c.chr("ENCODING")
+      c2 = (c + 0x20).chr("ENCODING")
+      assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+      assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+      assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+      assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+    end
+  )
+
+  def test_koi8_r
+    eval("# encoding: koi8-r\n" + ASSERTS.gsub("ENCODING", "koi8-r"))
+  end
+
+  def test_koi8_u
+    eval("# encoding: koi8-u\n" + ASSERTS.gsub("ENCODING", "koi8-u"))
+  end
+end

Property changes on: mvm/test/ruby/enc/test_koi8.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: mvm/test/ruby/test_io.rb
===================================================================
--- mvm/test/ruby/test_io.rb	(revision 18273)
+++ mvm/test/ruby/test_io.rb	(revision 18274)
@@ -557,14 +557,16 @@
     end.join
   end
 
-  def pipe
+  def pipe(wp, rp)
     r, w = IO.pipe
-    Timeout.timeout(10) do
-      yield(r, w)
-    end
+    rt = Thread.new { rp.call(r) }
+    wt = Thread.new { wp.call(w) }
+    flunk("timeout") unless rt.join(10) && wt.join(10)
   ensure
     r.close unless !r || r.closed?
     w.close unless !w || w.closed?
+    (rt.kill; rt.join) if rt
+    (wt.kill; wt.join) if wt
   end
 
   def pipe2(&b)
@@ -594,16 +596,20 @@
   end
 
   def test_ungetc2
-    pipe do |r, w|
-      r.ungetc("0" * 10000)
+    f = false
+    pipe(proc do |w|
+      0 until f
       w.write("1" * 10000)
       w.close
+    end, proc do |r|
+      r.ungetc("0" * 10000)
+      f = true
       assert_equal("0" * 10000 + "1" * 10000, r.read)
-    end
+    end)
   end
 
   def test_write_non_writable
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert_raise(IOError) do
         r.write "foobarbaz"
       end
@@ -629,7 +635,7 @@
   end
 
   def test_inspect
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert(r.inspect =~ /^#<IO:0x[0-9a-f]+>$/)
       assert_raise(SecurityError) do
         safe_4 { r.inspect }
@@ -638,18 +644,19 @@
   end
 
   def test_readpartial
-    pipe do |r, w|
+    pipe(proc do |w|
       w.write "foobarbaz"
       w.close
+    end, proc do |r|
       assert_raise(ArgumentError) { r.readpartial(-1) }
       assert_equal("fooba", r.readpartial(5))
       r.readpartial(5, s = "")
       assert_equal("rbaz", s)
-    end
+    end)
   end
 
   def test_readpartial_error
-    pipe do |r, w|
+    with_pipe do |r, w|
       s = ""
       t = Thread.new { r.readpartial(5, s) }
       0 until s.size == 5
@@ -661,18 +668,19 @@
   end
 
   def test_read
-    pipe do |r, w|
+    pipe(proc do |w|
       w.write "foobarbaz"
       w.close
+    end, proc do |r|
       assert_raise(ArgumentError) { r.read(-1) }
       assert_equal("fooba", r.read(5))
       r.read(nil, s = "")
       assert_equal("rbaz", s)
-    end
+    end)
   end
 
   def test_read_error
-    pipe do |r, w|
+    with_pipe do |r, w|
       s = ""
       t = Thread.new { r.read(5, s) }
       0 until s.size == 5
@@ -684,20 +692,22 @@
   end
 
   def test_write_nonblock
-    pipe do |r, w|
+    pipe(proc do |w|
       w.write_nonblock(1)
       w.close
+    end, proc do |r|
       assert_equal("1", r.read)
-    end
+    end)
   end
 
   def test_gets
-    pipe do |r, w|
+    pipe(proc do |w|
       w.write "foobarbaz"
       w.close
+    end, proc do |r|
       assert_equal("", r.gets(0))
-      assert_equal("foobarbaz", r.gets(9))
-    end
+      assert_equal("foobarbaz", s = r.gets(9))
+    end)
   end
 
   def test_close_read
@@ -709,14 +719,14 @@
   end
 
   def test_close_read_pipe
-    pipe do |r, w|
+    with_pipe do |r, w|
       r.close_read
       assert_raise(Errno::EPIPE) { w.write "foobarbaz" }
     end
   end
 
   def test_close_read_security_error
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert_raise(SecurityError) do
         safe_4 { r.close_read }
       end
@@ -724,7 +734,7 @@
   end
 
   def test_close_read_non_readable
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert_raise(IOError) do
         w.close_read
       end
@@ -740,7 +750,7 @@
   end
 
   def test_close_write_security_error
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert_raise(SecurityError) do
         safe_4 { r.close_write }
       end
@@ -748,7 +758,7 @@
   end
 
   def test_close_write_non_readable
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert_raise(IOError) do
         r.close_write
       end
@@ -802,111 +812,119 @@
       assert_equal("nil,1,2,2,1001,1001,1001,1,2,3,3", f.read.chomp.gsub("\n", ","))
     end
 
-    pipe do |r, w|
+    pipe(proc do |w|
       w.puts "foo"
       w.puts "bar"
       w.puts "baz"
       w.close
+    end, proc do |r|
       r.gets; assert_equal(1, $.)
       r.gets; assert_equal(2, $.)
       r.lineno = 1000; assert_equal(2, $.)
       r.gets; assert_equal(1001, $.)
       r.gets; assert_equal(1001, $.)
-    end
+    end)
   end
 
   def test_readline
-    pipe do |r, w|
+    pipe(proc do |w|
       w.puts "foo"
       w.puts "bar"
       w.puts "baz"
       w.close
+    end, proc do |r|
       r.readline; assert_equal(1, $.)
       r.readline; assert_equal(2, $.)
       r.lineno = 1000; assert_equal(2, $.)
       r.readline; assert_equal(1001, $.)
       assert_raise(EOFError) { r.readline }
-    end
+    end)
   end
 
   def test_each_char
-    pipe do |r, w|
+    pipe(proc do |w|
       w.puts "foo"
       w.puts "bar"
       w.puts "baz"
       w.close
+    end, proc do |r|
       a = []
       r.each_char {|c| a << c }
       assert_equal(%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"], a)
-    end
+    end)
   end
 
   def test_lines
-    pipe do |r, w|
+    pipe(proc do |w|
       w.puts "foo"
       w.puts "bar"
       w.puts "baz"
       w.close
+    end, proc do |r|
       e = r.lines
       assert_equal("foo\n", e.next)
       assert_equal("bar\n", e.next)
       assert_equal("baz\n", e.next)
       assert_raise(StopIteration) { e.next }
-    end
+    end)
   end
 
   def test_bytes
-    pipe do |r, w|
+    pipe(proc do |w|
       w.puts "foo"
       w.puts "bar"
       w.puts "baz"
       w.close
+    end, proc do |r|
       e = r.bytes
       (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
         assert_equal(c.ord, e.next)
       end
       assert_raise(StopIteration) { e.next }
-    end
+    end)
   end
 
   def test_chars
-    pipe do |r, w|
+    pipe(proc do |w|
       w.puts "foo"
       w.puts "bar"
       w.puts "baz"
       w.close
+    end, proc do |r|
       e = r.chars
       (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
         assert_equal(c, e.next)
       end
       assert_raise(StopIteration) { e.next }
-    end
+    end)
   end
 
   def test_readbyte
-    pipe do |r, w|
+    pipe(proc do |w|
       w.puts "foo"
       w.puts "bar"
       w.puts "baz"
       w.close
+    end, proc do |r|
       (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
         assert_equal(c.ord, r.readbyte)
       end
       assert_raise(EOFError) { r.readbyte }
-    end
+    end)
   end
 
   def test_readchar
-    pipe do |r, w|
+    pipe(proc do |w|
       w.puts "foo"
       w.puts "bar"
       w.puts "baz"
       w.close
+    end, proc do |r|
       (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
         assert_equal(c, r.readchar)
       end
       assert_raise(EOFError) { r.readchar }
-    end
+    end)
   end
 
   def test_close_on_exec
@@ -919,7 +937,7 @@
       assert_equal(false, f.close_on_exec?)
     end
 
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert_equal(false, r.close_on_exec?)
       r.close_on_exec = true
       assert_equal(true, r.close_on_exec?)
@@ -935,7 +953,7 @@
   end
 
   def test_close_security_error
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert_raise(SecurityError) do
         safe_4 { r.close }
       end
@@ -1034,7 +1052,7 @@
   def test_reopen
     t = make_tempfile
 
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert_raise(SecurityError) do
         safe_4 { r.reopen(t.path) }
       end
@@ -1070,11 +1088,12 @@
   end
 
   def test_printf
-    pipe do |r, w|
+    pipe(proc do |w|
       printf(w, "foo %s baz\n", "bar")
       w.close_write
+    end, proc do |r|
       assert_equal("foo bar baz\n", r.read)
-    end
+    end)
   end
 
   def test_print
@@ -1084,13 +1103,14 @@
   end
 
   def test_putc
-    pipe do |r, w|
+    pipe(proc do |w|
       w.putc "A"
       w.putc "BC"
       w.putc 68
       w.close_write
+    end, proc do |r|
       assert_equal("ABD", r.read)
-    end
+    end)
 
     assert_in_out_err([], "putc 65", %w(A), [])
   end
@@ -1098,19 +1118,21 @@
   def test_puts_recursive_array
     a = ["foo"]
     a << a
-    pipe do |r, w|
+    pipe(proc do |w|
       w.puts a
       w.close
+    end, proc do |r|
       assert_equal("foo\n[...]\n", r.read)
-    end
+    end)
   end
 
   def test_display
-    pipe do |r, w|
+    pipe(proc do |w|
       "foo".display(w)
       w.close
+    end, proc do |r|
       assert_equal("foo", r.read)
-    end
+    end)
 
     assert_in_out_err([], "'foo'.display", %w(foo), [])
   end
@@ -1132,7 +1154,7 @@
 
     assert_equal("foo\nbar\nbaz\n", File.read(t.path))
 
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert_raise(RuntimeError) do
         o = Object.new
         class << o; self; end.instance_eval do
@@ -1142,16 +1164,18 @@
       end
     end
 
-    pipe do |r, w|
-      r, w = IO.new(r), IO.new(w)
+    pipe(proc do |w|
+      w = IO.new(w)
       w.puts "foo"
       w.puts "bar"
       w.puts "baz"
       w.close
+    end, proc do |r|
+      r = IO.new(r)
       assert_equal("foo\nbar\nbaz\n", r.read)
-    end
+    end)
 
-    pipe do |r, w|
+    with_pipe do |r, w|
       assert_raise(ArgumentError) { IO.new(r, "r+") }
     end
 
Index: mvm/test/ruby/test_sleep.rb
===================================================================
--- mvm/test/ruby/test_sleep.rb	(revision 0)
+++ mvm/test/ruby/test_sleep.rb	(revision 18274)
@@ -0,0 +1,10 @@
+require 'test/unit'
+
+class TestSleep < Test::Unit::TestCase
+  def test_sleep_5sec
+    start = Time.now
+    sleep 5
+    slept = Time.now-start
+    assert_in_delta(5.0, slept, 0.1, "[ruby-core:18015]: longer than expected")
+  end
+end

Property changes on: mvm/test/ruby/test_sleep.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: mvm/test/win32ole/test_err_in_callback.rb
===================================================================
--- mvm/test/win32ole/test_err_in_callback.rb	(revision 0)
+++ mvm/test/win32ole/test_err_in_callback.rb	(revision 18274)
@@ -0,0 +1,73 @@
+#
+# test Win32OLE avoids cfp consistency error when the exception raised
+# in WIN32OLE_EVENT handler block. [ruby-dev:35450]
+#
+
+begin
+  require 'win32ole'
+rescue LoadError
+end
+require 'rbconfig'
+require 'mkmf'
+require 'test/unit'
+if defined?(WIN32OLE)
+  class TestErrInCallBack < Test::Unit::TestCase
+    def setup
+      @ruby = nil
+      if File.exist?("./" + CONFIG["RUBY_INSTALL_NAME"] + CONFIG["EXEEXT"])
+        @ruby = "./" + CONFIG["RUBY_INSTALL_NAME"]
+        @iopt = $:.map {|e|
+          " -I " + e
+        }.join("")
+        @script = File.dirname(__FILE__) + "/err_in_callback.rb"
+        @param = create_temp_html
+        @param = "file:///" + @param.gsub(/\\/, '/')
+      end
+    end
+
+    def create_temp_html
+      fso = WIN32OLE.new('Scripting.FileSystemObject')
+      dummy_file = fso.GetTempName + ".html"
+      cfolder = fso.getFolder(".")
+      @str = "This is test HTML file for Win32OLE (#{Time.now})"
+      f = cfolder.CreateTextFile(dummy_file)
+      f.writeLine("<html><body><div id='str'>#{@str}</div></body></html>")
+      f.close
+      dummy_path = cfolder.path + "\\" + dummy_file
+      dummy_path
+    end
+
+    def test_err_in_callback
+      if @ruby
+        r = `#{@ruby} #{@iopt} #{@script} #{@param}`
+        assert_match(/NameError/, r)
+      end
+    end
+
+    def ie_quit
+      sh = WIN32OLE.new('Shell.Application')
+      sh.windows.each do |w|
+        if w.ole_type.name == 'IWebBrowser2'
+          20.times do |i|
+            if w.locationURL != "" && w.document
+              break
+            end
+            WIN32OLE_EVENT.message_loop
+            sleep 1
+          end
+          e = w.document.getElementById("str")
+          if e && e.innerHTML == @str
+            w.quit
+            WIN32OLE_EVENT.message_loop
+            sleep 0.2
+          end
+        end
+      end
+    end
+
+    def teardown
+      WIN32OLE_EVENT.message_loop
+      ie_quit
+    end
+  end
+end

Property changes on: mvm/test/win32ole/test_err_in_callback.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: mvm/test/win32ole/err_in_callback.rb
===================================================================
--- mvm/test/win32ole/err_in_callback.rb	(revision 0)
+++ mvm/test/win32ole/err_in_callback.rb	(revision 18274)
@@ -0,0 +1,11 @@
+require 'win32ole'
+ie = WIN32OLE.new('InternetExplorer.Application')
+ie.visible = true
+WIN32OLE_EVENT.message_loop
+sleep 0.2
+ev = WIN32OLE_EVENT.new(ie)
+
+ev.on_event('BeforeNavigate2') {|*args|
+  foo
+}
+ie.navigate(ARGV.shift)

Property changes on: mvm/test/win32ole/err_in_callback.rb
___________________________________________________________________
Name: svn:eol-style
   + LF

Index: mvm/test/win32ole/test_win32ole_event.rb
===================================================================
--- mvm/test/win32ole/test_win32ole_event.rb	(revision 18273)
+++ mvm/test/win32ole/test_win32ole_event.rb	(revision 18274)
@@ -6,6 +6,8 @@
 
 if defined?(WIN32OLE_EVENT)
   class TestWIN32OLE_EVENT < Test::Unit::TestCase
+    module IE
+    end
     def create_temp_html
       fso = WIN32OLE.new('Scripting.FileSystemObject')
       dummy_file = fso.GetTempName + ".html"
@@ -17,9 +19,25 @@
       dummy_path
     end
 
+    def message_loop
+      WIN32OLE_EVENT.message_loop
+      sleep 0.1
+    end
+
+    def wait_ie
+      while @ie.readyState != IE::READYSTATE_COMPLETE
+        message_loop
+      end
+    end
+
     def setup
+      WIN32OLE_EVENT.message_loop
       @ie = WIN32OLE.new("InternetExplorer.Application")
+      if !defined?(IE::READYSTATE_COMPLETE)
+        WIN32OLE.const_load(@ie, IE)
+      end
       @ie.visible = true
+      message_loop
       @event = ""
       @event2 = ""
       @event3 = ""
@@ -43,8 +61,7 @@
       while @ie.busy
         WIN32OLE_EVENT.new(@ie)
         GC.start  
-        WIN32OLE_EVENT.message_loop
-        sleep 0.1
+        message_loop
       end
       assert_match(/BeforeNavigate/, @event)
       assert_match(/NavigateComplete/, @event)
@@ -54,11 +71,7 @@
       ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
       ev.on_event {|*args| default_handler(*args)}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents') 
-        GC.start  
-        sleep 0.1
-      end
+      wait_ie
       assert_match(/BeforeNavigate/, @event)
       assert_match(/NavigateComplete/, @event)
     end
@@ -68,10 +81,7 @@
       ev.on_event('BeforeNavigate') {|*args| handler1}
       ev.on_event('BeforeNavigate') {|*args| handler2}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        WIN32OLE_EVENT.message_loop
-        sleep 0.1
-      end
+      wait_ie
       assert_equal("handler2", @event2)
     end
 
@@ -80,10 +90,7 @@
       ev.on_event {|*args| handler1}
       ev.on_event {|*args| handler2}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        WIN32OLE_EVENT.message_loop
-        sleep 0.1
-      end
+      wait_ie
       assert_equal("handler2", @event2)
     end
 
@@ -93,10 +100,7 @@
       ev.on_event{|*args| handler2}
       ev.on_event('NavigateComplete'){|*args| handler3(*args)}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        WIN32OLE_EVENT.message_loop
-        sleep 0.1
-      end
+      wait_ie
       assert(@event3!="")
       assert("handler2", @event2)
     end
@@ -106,10 +110,7 @@
       ev.on_event {|*args| default_handler(*args)}
       ev.on_event('NavigateComplete'){|*args| handler3(*args)}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        WIN32OLE_EVENT.message_loop
-        sleep 0.1
-      end
+      wait_ie
       assert_match(/BeforeNavigate/, @event)
       assert(/NavigateComplete/ !~ @event)
       assert(@event!="")
@@ -119,18 +120,12 @@
       ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
       ev.on_event {|*args| default_handler(*args)}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        WIN32OLE_EVENT.message_loop
-        sleep 0.1
-      end
+      wait_ie
       assert_match(/BeforeNavigate/, @event)
       ev.unadvise
       @event = ""
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        WIN32OLE_EVENT.message_loop
-        sleep 0.1
-      end
+      wait_ie
       assert_equal("", @event);
       assert_raise(WIN32OLERuntimeError) {
         ev.on_event {|*args| default_handler(*args)}
@@ -157,10 +152,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        sleep 0.1
-        WIN32OLE_EVENT.message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
 
@@ -171,10 +163,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        sleep 0.1
-        WIN32OLE_EVENT.message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
 
@@ -185,10 +174,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        sleep 0.1
-        WIN32OLE_EVENT.message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
 
@@ -199,10 +185,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        sleep 0.1
-        WIN32OLE_EVENT.message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
     
@@ -213,10 +196,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        sleep 0.1
-        WIN32OLE_EVENT.message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
 
@@ -227,13 +207,28 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        sleep 0.1
-        WIN32OLE_EVENT.message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
 
+    def test_off_event
+      ev = WIN32OLE_EVENT.new(@ie)
+      ev.on_event{handler1}
+      ev.off_event
+      @ie.navigate("file:///#{@f}")
+      wait_ie
+      assert_equal("", @event2)
+    end
+
+    def test_off_event_arg
+      ev = WIN32OLE_EVENT.new(@ie)
+      ev.on_event('BeforeNavigate2'){handler1}
+      ev.off_event('BeforeNavigate2')
+      @ie.navigate("file:///#{@f}")
+      wait_ie
+      assert_equal("", @event2)
+    end
+
     def handler1
       @event2 = "handler1"
     end
@@ -248,21 +243,72 @@
 
     def teardown
       @ie.quit
-      WIN32OLE_EVENT.message_loop
+      message_loop
       @ie = nil
-      WIN32OLE_EVENT.message_loop
-      sleep 0.1
+      i = 0
       begin 
-        File.unlink(@f)
+        i += 1
+        File.unlink(@f) if i < 10
       rescue Errno::EACCES
-        WIN32OLE_EVENT.message_loop
-        sleep 0.1
-        File.unlink(@f)
+        message_loop
+        retry
       end
-
+      message_loop
       GC.start
-      WIN32OLE_EVENT.message_loop
-      sleep 0.1
+      message_loop
     end
+
+    class Handler1
+      attr_reader :val1, :val2, :val3, :val4
+      def initialize
+        @val1 = nil
+        @val2 = nil
+        @val3 = nil
+        @val4 = nil
+      end
+      def onStatusTextChange(t)
+        @val1 = t
+      end
+      def onProgressChange(p, pmax)
+        @val2 = p
+        @val3 = pmax
+      end
+      def onPropertyChange(p)
+        @val4 = p
+      end
+    end
+
+    class Handler2
+      attr_reader :ev
+      def initialize
+        @ev = ""
+      end
+      def method_missing(ev, *arg)
+        @ev += ev
+      end
+    end
+
+    def test_handler1
+      ev = WIN32OLE_EVENT.new(@ie)
+      h1 = Handler1.new
+      ev.handler = h1
+      @ie.navigate("file:///#{@f}")
+      wait_ie
+      assert(h1.val1)
+      assert_equal(h1.val1, ev.handler.val1)
+      assert(h1.val2)
+      assert(h1.val3)
+      assert(h1.val4)
+    end
+
+    def test_handler2
+      ev = WIN32OLE_EVENT.new(@ie)
+      h2 = Handler2.new
+      ev.handler = h2
+      @ie.navigate("file:///#{@f}")
+      wait_ie
+      assert(h2.ev != "")
+    end
+
   end
 end
Index: mvm/test/openssl/test_ssl.rb
===================================================================
--- mvm/test/openssl/test_ssl.rb	(revision 18273)
+++ mvm/test/openssl/test_ssl.rb	(revision 18274)
@@ -86,7 +86,7 @@
         server_proc.call(ctx, ssl)
       end
     end
-  rescue Errno::EBADF, IOError
+  rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED
   end
 
   def start_server(port0, verify_mode, start_immediately, args = {}, &block)
@@ -128,8 +128,8 @@
 
       block.call(server, port.to_i)
     ensure
-      tcps.shutdown if (tcps)
       begin
+        tcps.shutdown if (tcps)
         if (server)
           server.join(5)
           if server.alive?
@@ -138,7 +138,6 @@
             flunk("TCPServer was closed and SSLServer is still alive") unless $!
           end
         end
-      rescue Errno::EINVAL, Errno::EBADF
       ensure
         tcps.close if (tcps)
       end
Index: mvm/test/rinda/test_rinda.rb
===================================================================
--- mvm/test/rinda/test_rinda.rb	(revision 18273)
+++ mvm/test/rinda/test_rinda.rb	(revision 18274)
@@ -12,14 +12,14 @@
   include Singleton
 
   class MyTS < Rinda::TupleSpace
-    def keeper
+    def keeper_thread
       nil
     end
   end
   
   def initialize
     @now = 2
-    @reso = 0.1
+    @reso = 1
     @ts = MyTS.new
     @ts.write([2, :now])
     @inf = 2**31 - 1
@@ -33,17 +33,18 @@
     n
   end
     
-  def _forward(n=@reso)
+  def _forward(n=nil)
     now ,= @ts.take([nil, :now])
     @now = now + n
     n = @reso if n.nil?
     @ts.write([@now, :now])
   end
 
-  def forward(n=@reso)
+  def forward(n)
     while n > 0
       _forward(@reso)
       n -= @reso
+      Thread.pass
     end
   end
 
@@ -55,21 +56,11 @@
     @ts.write([2, :now])
   end
 
-  def sleep(n=@reso)
-    while will_deadlock? 
-      n -= @reso
-      forward
-      return 0 if n <= 0
-    end
+  def sleep(n=nil)
     now ,= @ts.read([nil, :now])
     @ts.read([(now + n)..@inf, :now])
     0
   end
-
-  def will_deadlock?
-    sz = Thread.current.group.list.find_all {|x| x.status != 'sleep'}.size
-    sz <= 1
-  end
 end
 
 module Time
@@ -115,6 +106,14 @@
       Time.sleep(n)
     end
   end
+
+  def thread_join(th)
+    while th.alive?
+      Kernel.sleep(0.1)
+      sleep(1)
+    end
+    th.value
+  end
   
   def test_00_tuple
     tuple = Rinda::TupleEntry.new([1,2,3])
@@ -240,6 +239,28 @@
     end
   end
 
+  def test_ruby_talk_264062
+    th = Thread.new { @ts.take([:empty], 1) }
+    sleep(10)
+    assert_raises(Rinda::RequestExpiredError) do
+      thread_join(th)
+    end
+
+    th = Thread.new { @ts.read([:empty], 1) }
+    sleep(10)
+    assert_raises(Rinda::RequestExpiredError) do
+      thread_join(th)
+    end
+  end
+
+  def test_symbol_tuple
+    @ts.write([:symbol, :symbol])
+    @ts.write(['string', :string])
+    assert_equal([[:symbol, :symbol]], @ts.read_all([:symbol, nil]))
+    assert_equal([[:symbol, :symbol]], @ts.read_all([Symbol, nil]))
+    assert_equal([], @ts.read_all([:nil, nil]))
+  end
+
   def test_core_01
     5.times do |n|
       @ts.write([:req, 2])
@@ -252,7 +273,7 @@
       s = 0
       while true
 	begin
-	  tuple = @ts.take([:req, Integer], 0.5)
+	  tuple = @ts.take([:req, Integer], 1)
 	  assert_equal(2, tuple[1])
 	  s += tuple[1]
 	rescue Rinda::RequestExpiredError
@@ -263,10 +284,9 @@
       s
     end
     
-    sleep(20)
+    assert_equal(10, thread_join(taker))
     tuple = @ts.take([:ans, nil])
     assert_equal(10, tuple[1])
-    assert_equal(10, taker.value)
   end
 
   def test_core_02
@@ -274,7 +294,7 @@
       s = 0
       while true
 	begin
-	  tuple = @ts.take([:req, Integer], 1.0)
+	  tuple = @ts.take([:req, Integer], 1)
 	  assert_equal(2, tuple[1])
 	  s += tuple[1]
 	rescue Rinda::RequestExpiredError
@@ -289,10 +309,9 @@
       @ts.write([:req, 2])
     end
 
-    sleep(20)
+    assert_equal(10, thread_join(taker))
     tuple = @ts.take([:ans, nil])
     assert_equal(10, tuple[1])
-    assert_equal(10, taker.value)
     assert_equal([], @ts.read_all([nil, nil]))
   end
   
@@ -349,7 +368,7 @@
       s = 0
       while true
 	begin
-	  tuple = @ts.take([:req, Integer], 1.0)
+	  tuple = @ts.take([:req, Integer], 1)
 	  s += tuple[1]
 	rescue Rinda::RequestExpiredError
 	  break
@@ -359,26 +378,23 @@
       s
     end
 
-    writer = Thread.new do
-      5.times do |n|
-	@ts.write([:req, 2])
-	sleep 0.1
-      end
+    5.times do |n|
+      @ts.write([:req, 2])
     end
 
     @ts.take({"message"=>"first", "name"=>"3"})
 
     sleep(4)
+    assert_equal(10, thread_join(taker))
     tuple = @ts.take([:ans, nil])
     assert_equal(10, tuple[1])
-    assert_equal(10, taker.value)
     assert_equal([], @ts.read_all([nil, nil]))
     
     notify1.cancel
     sleep(3) # notify2 expired
     
-    assert_equal([0, 11], listener1.value)
-    assert_equal([0, 3], listener2.value)
+    assert_equal([0, 11], thread_join(listener1))
+    assert_equal([0, 3], thread_join(listener2))
 
     ary = []
     ary.push(["write", {"message"=>"first", "name"=>"3"}])
@@ -403,23 +419,24 @@
     
     template = nil
     taker = Thread.new do
-      @ts.take([:take, nil], 10) do |template|
+      @ts.take([:take, nil], 10) do |t|
+        template = t
 	Thread.new do
-	  sleep 0.2
 	  template.cancel
 	end
       end
     end
     
-    sleep(1)
+    sleep(2)
+
+    assert_raises(Rinda::RequestCanceledError) do
+      assert_nil(thread_join(taker))
+    end
+
     assert(template.canceled?)
     
     @ts.write([:take, 1])
 
-    assert_raises(Rinda::RequestCanceledError) do
-      assert_nil(taker.value)
-    end
-
     assert_equal([[:take, 1]], @ts.read_all([nil, nil]))
   end
 
@@ -431,23 +448,24 @@
 
     template = nil
     reader = Thread.new do
-      @ts.read([:take, nil], 10) do |template|
+      @ts.read([:take, nil], 10) do |t|
+        template = t
 	Thread.new do
-	  sleep 0.2
 	  template.cancel
 	end
       end
     end
 
-    sleep(1)
+    sleep(2)
+
+    assert_raises(Rinda::RequestCanceledError) do
+      assert_nil(thread_join(reader))
+    end
+
     assert(template.canceled?)
     
     @ts.write([:take, 1])
 
-    assert_raises(Rinda::RequestCanceledError) do
-      assert_nil(reader.value)
-    end
-
     assert_equal([[:take, 1]], @ts.read_all([nil, nil]))
   end
 
@@ -478,30 +496,22 @@
     assert(tuple.expired?)
     assert(!tuple.alive?)
 
-    tuple = Rinda::TupleEntry.new([1,2,3], SimpleRenewer.new(1,2))
+    @renewer = SimpleRenewer.new(1,2)
+    tuple = Rinda::TupleEntry.new([1,2,3], @renewer)
     assert(!tuple.canceled?)
     assert(!tuple.expired?)
     assert(tuple.alive?)
-    sleep(1.5)
+    sleep(1)
     assert(!tuple.canceled?)
     assert(!tuple.expired?)
     assert(tuple.alive?)
-    sleep(1.5)
+    sleep(2)
     assert(tuple.expired?)
     assert(!tuple.alive?)
   end
 end
 
 class TupleSpaceTest < Test::Unit::TestCase
-  def test_message
-    flunk("YARV doesn't support Rinda")
-  end
-end
-
-end
-__END__
-
-class TupleSpaceTest < Test::Unit::TestCase
   include TupleSpaceTestModule
 
   def setup
@@ -520,13 +530,9 @@
   end
 
   def test_remote_array_and_hash
-    ary = [1, 2, 3]
-    @ts.write(DRbObject.new(ary))
-    GC.start
+    @ts.write(DRbObject.new([1, 2, 3]))
     assert_equal([1, 2, 3], @ts.take([1, 2, 3], 0))
-    hash = {'head' => 1, 'tail' => 2}
-    @ts.write(DRbObject.new(hash))
-    GC.start
+    @ts.write(DRbObject.new({'head' => 1, 'tail' => 2}))
     assert_equal({'head' => 1, 'tail' => 2},
                  @ts.take({'head' => 1, 'tail' => 2}, 0))
   end
Index: mvm/test/rss/rss-assertions.rb
===================================================================
--- mvm/test/rss/rss-assertions.rb	(revision 18273)
+++ mvm/test/rss/rss-assertions.rb	(revision 18274)
@@ -557,20 +557,16 @@
 
     def assert_atom_content_inline_other_text(generator)
       _wrap_assertion do
-        require "zlib"
-
-        type = "application/zip"
+        type = "image/png"
         assert_parse(generator.call(<<-EOA), :nothing_raised)
   <content type="#{type}"/>
 EOA
 
-        text = ""
-        char = "a"
-        100.times do |i|
-          text << char
-          char.succ!
+        png_file = File.join(File.dirname(__FILE__), "dot.png")
+        png = File.open(png_file, "rb") do |file|
+          file.read.force_encoding("binary")
         end
-        base64_content = [Zlib::Deflate.deflate(text)].pack("m").delete("\n")
+        base64_content = [png].pack("m").delete("\n")
 
         [false, true].each do |with_space|
           xml_content = base64_content
@@ -591,7 +587,7 @@
           assert(content.inline_other_base64?)
           assert(!content.out_of_line?)
           assert(!content.have_xml_content?)
-          assert_equal(text, Zlib::Inflate.inflate(content.content))
+          assert_equal(png, content.content)
 
           xml = REXML::Document.new(content.to_s).root
           assert_rexml_element([], {"type" => type}, base64_content, xml)
Index: mvm/test/rss/dot.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = image/png

Property changes on: mvm/test/rss/dot.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Index: mvm/test/rss/test_atom.rb
===================================================================
--- mvm/test/rss/test_atom.rb	(revision 18273)
+++ mvm/test/rss/test_atom.rb	(revision 18274)
@@ -641,24 +641,19 @@
 
     def assert_atom_content_inline_other_base64_to_s(target_class)
       _wrap_assertion do
-        require "zlib"
-
-        text = ""
-        char = "a"
-        100.times do |i|
-          text << char
-          char.succ!
+        type = "image/png"
+        png_file = File.join(File.dirname(__FILE__), "dot.png")
+        original_content = File.open(png_file, "rb") do |file|
+          file.read.force_encoding("binary")
         end
 
-        type = "application/zip"
-        original_content = Zlib::Deflate.deflate(text)
-
         content = target_class.new
         content.type = type
         content.content = original_content
         xml = REXML::Document.new(content.to_s).root
         assert_rexml_element([], {"type" => type},
-                             [original_content].pack("m").delete("\n"), xml)
+                             [original_content].pack("m").delete("\n"),
+                             xml)
       end
     end
 
Index: mvm/test/etc/test_etc.rb
===================================================================
--- mvm/test/etc/test_etc.rb	(revision 18273)
+++ mvm/test/etc/test_etc.rb	(revision 18274)
@@ -18,7 +18,7 @@
       assert_instance_of(String, s.shell)
       assert_kind_of(Integer, s.change) if s.respond_to?(:change)
       assert_kind_of(Integer, s.quota) if s.respond_to?(:quota)
-      assert_kind_of(Integer, s.age) if s.respond_to?(:age)
+      assert(s.age.is_a?(Integer) || s.age.is_a?(String)) if s.respond_to?(:age)
       assert_instance_of(String, s.uclass) if s.respond_to?(:uclass)
       assert_instance_of(String, s.comment) if s.respond_to?(:comment)
       assert_kind_of(Integer, s.expire) if s.respond_to?(:expire)
@@ -28,9 +28,9 @@
   end
 
   def test_getpwuid
-    passwd = []
-    Etc.passwd {|s| passwd << s }
-    passwd.each do |s|
+    passwd = {}
+    Etc.passwd {|s| passwd[s.uid] = s unless passwd[s.uid] }
+    passwd.values.each do |s|
       assert_equal(s, Etc.getpwuid(s.uid))
       assert_equal(s, Etc.getpwuid) if Etc.getlogin == s.name
     end
Index: mvm/file.c
===================================================================
--- mvm/file.c	(revision 18273)
+++ mvm/file.c	(revision 18274)
@@ -4479,35 +4479,25 @@
     return eaccess(path, R_OK) == 0;
 }
 
-#ifdef __CYGWIN__
-static void
-intern_cygwin_path(volatile VALUE *path)
+static int
+is_explicit_relative(const char *path)
 {
-    char rubylib[MAXPATHLEN];
-    VALUE str = *path;
-    const char *p = RSTRING_PTR(str);
-
-    if (*p == '\\' || has_drive_letter(p)) {
-	if (cygwin_conv_to_posix_path(p, rubylib) == 0) {
-	    *path = rb_str_new2(rubylib);
-	}
-    }
+    if (*path++ != '.') return 0;
+    if (*path == '.') path++;
+    return isdirsep(*path);
 }
-#define intern_path(str) intern_cygwin_path(&(str))
-#else
-#define intern_path(str) (void)(str)
-#endif
 
 VALUE rb_get_load_path(void);
 
 int
 rb_find_file_ext(VALUE *filep, const char *const *ext)
 {
-    const char *path, *found;
     const char *f = RSTRING_PTR(*filep);
-    VALUE fname, load_path;
-    long i, j;
+    VALUE fname, load_path, tmp;
+    long i, j, fnlen;
 
+    if (!ext[0]) return 0;
+
     if (f[0] == '~') {
 	fname = rb_file_expand_path(*filep, Qnil);
 	if (rb_safe_level() >= 2 && OBJ_TAINTED(fname)) {
@@ -4518,15 +4508,18 @@
 	*filep = fname;
     }
 
-    if (is_absolute_path(f)) {
+    if (is_absolute_path(f) || is_explicit_relative(f)) {
+	fname = rb_str_dup(*filep);
+	fnlen = RSTRING_LEN(fname);
 	for (i=0; ext[i]; i++) {
-	    fname = rb_str_dup(*filep);
 	    rb_str_cat2(fname, ext[i]);
-	    OBJ_FREEZE(fname);
 	    if (file_load_ok(StringValueCStr(fname))) {
+		if (!is_absolute_path(f)) fname = rb_file_expand_path(fname, Qnil);
+		OBJ_FREEZE(fname);
 		*filep = fname;
 		return i+1;
 	    }
+	    rb_str_set_len(fname, fnlen);
 	}
 	return 0;
     }
@@ -4534,24 +4527,26 @@
     load_path = rb_get_load_path();
     if (!load_path) return 0;
 
+    fname = rb_str_dup(*filep);
+    RBASIC(fname)->klass = 0;
+    fnlen = RSTRING_LEN(fname);
+    tmp = rb_str_tmp_new(MAXPATHLEN + 2);
     for (j=0; ext[j]; j++) {
-	fname = rb_str_dup(*filep);
 	rb_str_cat2(fname, ext[j]);
-	OBJ_FREEZE(fname);
 	for (i = 0; i < RARRAY_LEN(load_path); i++) {
 	    VALUE str = RARRAY_PTR(load_path)[i];
-	    char fbuf[MAXPATHLEN];
 
 	    FilePathValue(str);
 	    if (RSTRING_LEN(str) == 0) continue;
-	    intern_path(str);
-	    path = RSTRING_PTR(str);
-	    found = dln_find_file_r(StringValueCStr(fname), path, fbuf, sizeof(fbuf));
-	    if (found && file_load_ok(found)) {
-		*filep = rb_str_new2(found);
+	    file_expand_path(fname, str, tmp);
+	    if (file_load_ok(RSTRING_PTR(tmp))) {
+		RBASIC(tmp)->klass = RBASIC(*filep)->klass;
+		OBJ_FREEZE(tmp);
+		*filep = tmp;
 		return j+1;
 	    }
 	}
+	rb_str_set_len(fname, fnlen);
     }
     RB_GC_GUARD(load_path);
     return 0;
@@ -4562,8 +4557,6 @@
 {
     VALUE tmp, load_path;
     const char *f = StringValueCStr(path);
-    const char *lpath;
-    char fbuf[MAXPATHLEN];
 
     if (f[0] == '~') {
 	path = rb_file_expand_path(path, Qnil);
@@ -4580,14 +4573,17 @@
 	    rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
 	}
 	if (file_load_ok(f)) return path;
+	return 0;
     }
 #endif
 
-    if (is_absolute_path(f)) {
+    if (is_absolute_path(f) || is_explicit_relative(f)) {
 	if (rb_safe_level() >= 1 && !fpath_check(f)) {
 	    rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
 	}
-	if (file_load_ok(f)) return path;
+	if (!file_load_ok(f)) return 0;
+	if (!is_absolute_path(f)) path = rb_file_expand_path(path, Qnil);
+	return path;
     }
 
     if (rb_safe_level() >= 4) {
@@ -4598,42 +4594,30 @@
     if (load_path) {
 	long i;
 
-	tmp = rb_ary_new();
+	tmp = rb_str_tmp_new(MAXPATHLEN + 2);
 	for (i = 0; i < RARRAY_LEN(load_path); i++) {
 	    VALUE str = RARRAY_PTR(load_path)[i];
 	    FilePathValue(str);
 	    if (RSTRING_LEN(str) > 0) {
-		intern_path(str);
-		rb_ary_push(tmp, str);
+		file_expand_path(path, str, tmp);
+		f = RSTRING_PTR(tmp);
+		if (file_load_ok(f)) goto found;
 	    }
 	}
-	tmp = rb_ary_join(tmp, rb_str_new2(PATH_SEP));
-	if (RSTRING_LEN(tmp) == 0) {
-	    lpath = 0;
-	}
-	else {
-	    lpath = RSTRING_PTR(tmp);
-	}
+	return 0;
+      found:
+	RBASIC(tmp)->klass = RBASIC(path)->klass;
+	OBJ_FREEZE(tmp);
     }
     else {
-	lpath = 0;
-    }
-
-    if (!lpath) {
 	return 0;		/* no path, no load */
     }
-    if (!(f = dln_find_file_r(f, lpath, fbuf, sizeof(fbuf)))) {
-	return 0;
-    }
+
     if (rb_safe_level() >= 1 && !fpath_check(f)) {
 	rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
     }
-    if (file_load_ok(f)) {
-	tmp = rb_str_new2(f);
-	OBJ_FREEZE(tmp);
-	return tmp;
-    }
-    return 0;
+
+    return tmp;
 }
 
 static void

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]