From: nobuyoshi nakada Date: 2005-12-16T12:12:15+09:00 Subject: Re: [PATCH] Re: IO.open not calling close in block form? Hi, At Fri, 16 Dec 2005 10:45:35 +0900, Mauricio Fernandez wrote in [ruby-core:06912]: > What about this? It won't work fine if closed? method is overridden. I think the original problem posted at [ruby-dev:27156] is which should be honored, a jump from the body or one from the ensure clause. Currently, this code just returns an exception instead of raising it. def protect yield ensure return $! end p protect {raise} # => RuntimeError, not `unhandled exception' One thought is to give priority to the body than the ensure clause. That is to let the following code raise "foo" instead of "bar". begin raise "foo" ensure raise "bar" end Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.616.2.140 diff -U2 -p -u -r1.616.2.140 eval.c --- eval.c 12 Dec 2005 03:36:48 -0000 1.616.2.140 +++ eval.c 16 Dec 2005 02:17:50 -0000 @@ -995,4 +995,20 @@ static struct tag *prot_tag; #define TAG_DST() (_tag.dst == (VALUE)ruby_frame->uniq) +#define ENSURE_PROC(state, ensures) do { \ + volatile VALUE retval = prot_tag ? prot_tag->retval : Qnil; \ + volatile VALUE errinfo = ruby_errinfo; \ + \ + if (state) { \ + PUSH_TAG(PROT_NONE); \ + if (!EXEC_TAG()) {ensures;} \ + POP_TAG(); \ + } \ + else { \ + ensures; \ + } \ + if (prot_tag) return_value(retval); \ + ruby_errinfo = errinfo; \ + } while (0) + #define TAG_RETURN 0x1 #define TAG_BREAK 0x2 @@ -3247,10 +3263,5 @@ rb_eval(self, n) POP_TAG(); if (node->nd_ensr) { - VALUE retval = prot_tag->retval; /* save retval */ - VALUE errinfo = ruby_errinfo; - - rb_eval(self, node->nd_ensr); - return_value(retval); - ruby_errinfo = errinfo; + ENSURE_PROC(state, rb_eval(self, node->nd_ensr)); } if (state) JUMP_TAG(state); @@ -5356,5 +5367,4 @@ rb_ensure(b_proc, data1, e_proc, data2) int state; volatile VALUE result = Qnil; - VALUE retval; PUSH_TAG(PROT_NONE); @@ -5363,7 +5373,5 @@ rb_ensure(b_proc, data1, e_proc, data2) } POP_TAG(); - retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */ - (*e_proc)(data2); - if (prot_tag) return_value(retval); + ENSURE_PROC(state, (*e_proc)(data2)); if (state) JUMP_TAG(state); return result; Index: io.c =================================================================== RCS file: /cvs/ruby/src/ruby/io.c,v retrieving revision 1.246.2.93 diff -U2 -p -r1.246.2.93 io.c --- io.c 12 Dec 2005 03:36:49 -0000 1.246.2.93 +++ io.c 16 Dec 2005 01:12:07 -0000 @@ -2151,8 +2151,4 @@ io_close(io) VALUE io; { - if (TYPE(io) == T_FILE) { - rb_io_close(io); - return Qnil; - } return rb_funcall(io, rb_intern("close"), 0, 0); } -- Nobu Nakada