Project

General

Profile

Actions

Bug #1105

closed

Ruby1.9でのrescue節の例外ハンドラのマッチの処理

Added by tkawai (Tatsuji Kawai) over 16 years ago. Updated about 14 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 1.9.2dev (2009-02-02 trunk 21974)
Backport:
[ruby-dev:37898]

Description

=begin
河井です。

Ruby1.9とRuby1.8では、例外ハンドルクラスのリストにExceptionのサブ
クラス以外のオブジェクトが含まれている場合の挙動に違いがあります。

例えば以下のプログラムを実行した場合、

begin
raise
rescue Object.new, RuntimeError => e
p e
end

ruby 1.9.2dev (2009-02-02 trunk 21974)
[i686-linux]の場合の実行結果以下で

=> RuntimeError

Object.new が無視され、例外が補足されるようです。

ruby 1.8.7 (2008-08-11 patchlevel 72)
[i486-linux]の場合の実行結果は

=> /tmp/test.rb:3: class or module required for rescue clause (TypeError)

となり、Object.neweがExceptionのサブクラスでないので例外が発生します。

参考までに、以下のコードの実行結果は1.9と1.8とも同で
RuntimeErrorが補足される結果となります。

begin
raise
rescue RuntimeError, Object.new => e
p e
end

--
河井達治
=end

Actions #1

Updated by nobu (Nobuyoshi Nakada) over 16 years ago

=begin
なかだです。

At Wed, 4 Feb 2009 16:45:09 +0900,
Tatsuji Kawai wrote in [ruby-dev:37898]:

Ruby1.9とRuby1.8では、例外ハンドルクラスのリストにExceptionのサブ
クラス以外のオブジェクトが含まれている場合の挙動に違いがあります。

これでどうでしょうか。


Index: compile.c

--- compile.c (revision 22030)
+++ compile.c (working copy)
@@ -3488,7 +3488,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_
case NODE_ARRAY:
while (narg) {

  •  	ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
     	COMPILE(ret, "rescue arg", narg->nd_head);
     	ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
    
  •  	ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1));
    
  •  	ADD_SEND(ret, nd_line(node), ID2SYM(id_core_handle_rescue_single), INT2FIX(2));
     	ADD_INSNL(ret, nd_line(node), branchif, label_hit);
     	narg = narg->nd_next;
    

@@ -3498,9 +3499,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_
case NODE_ARGSCAT:
case NODE_ARGSPUSH:

  •      ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
    
  •      ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
         COMPILE(ret, "rescue/cond splat", narg);
    
  •      ADD_INSN1(ret, nd_line(node), checkincludearray, Qtrue);
    
  •      ADD_INSN(ret, nd_line(node), swap);
    
  •      ADD_INSN(ret, nd_line(node), pop);
    
  •      ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
    
  •      ADD_SEND(ret, nd_line(node), ID2SYM(id_core_handle_rescue_array), INT2FIX(2));
         ADD_INSNL(ret, nd_line(node), branchif, label_hit);
         break;
    

Index: id.c

--- id.c (revision 22030)
+++ id.c (working copy)
@@ -22,15 +22,17 @@ Init_id(void)

  REGISTER_SYMID(idNULL, "");
  • REGISTER_SYMID(idIFUNC, ""),
  • REGISTER_SYMID(idCFUNC, ""),
  • REGISTER_SYMID(idRespond_to, "respond_to?"),
  • REGISTER_SYMID(idThrowState, "#ThrowState"),
  • REGISTER_SYMID(idIFUNC, "");
  • REGISTER_SYMID(idCFUNC, "");
  • REGISTER_SYMID(idRespond_to, "respond_to?");
  • REGISTER_SYMID(idThrowState, "#ThrowState");
  • REGISTER_SYMID(id_core_set_method_alias, "core#set_method_alias"),
  • REGISTER_SYMID(id_core_set_variable_alias, "core#set_variable_alias"),
  • REGISTER_SYMID(id_core_undef_method, "core#undef_method"),
  • REGISTER_SYMID(id_core_define_method, "core#define_method"),
  • REGISTER_SYMID(id_core_define_singleton_method, "core#define_singleton_method"),
  • REGISTER_SYMID(id_core_set_postexe, "core#set_postexe"),
  • REGISTER_SYMID(id_core_set_method_alias, "core#set_method_alias");

  • REGISTER_SYMID(id_core_set_variable_alias, "core#set_variable_alias");

  • REGISTER_SYMID(id_core_undef_method, "core#undef_method");

  • REGISTER_SYMID(id_core_define_method, "core#define_method");

  • REGISTER_SYMID(id_core_define_singleton_method, "core#define_singleton_method");

  • REGISTER_SYMID(id_core_set_postexe, "core#set_postexe");

  • REGISTER_SYMID(id_core_handle_rescue_single, "core#handle_rescue_single");

  • REGISTER_SYMID(id_core_handle_rescue_array, "core#handle_rescue_array");

    REGISTER_SYMID(idEach, "each");
    Index: id.h
    ===================================================================
    --- id.h (revision 22030)
    +++ id.h (working copy)
    @@ -69,5 +69,7 @@ enum ruby_method_ids {
    id_core_define_singleton_method = 374,
    id_core_set_postexe = 375,

  • tLAST_TOKEN = 376,
  • id_core_handle_rescue_single = 376,
  • id_core_handle_rescue_array = 377,
  • tLAST_TOKEN = 378,
    #endif
    idPLUS = '+',
    @@ -157,5 +159,7 @@ ruby_method_id_check_for(id_core_define_
    ruby_method_id_check_for(id_core_define_singleton_method, 374);
    ruby_method_id_check_for(id_core_set_postexe, 375);
    -ruby_method_id_check_for(tLAST_TOKEN, 376);
    +ruby_method_id_check_for(id_core_handle_rescue_single, 376);
    +ruby_method_id_check_for(id_core_handle_rescue_array, 377);
    +ruby_method_id_check_for(tLAST_TOKEN, 378);
    };
    #endif
    Index: parse.y
    ===================================================================
    --- parse.y (revision 22030)
    +++ parse.y (working copy)
    @@ -758,4 +758,6 @@ static void token_info_pop(struct parser
    %nonassoc id_core_define_singleton_method
    %nonassoc id_core_set_postexe
    +%nonassoc id_core_handle_rescue_single
    +%nonassoc id_core_handle_rescue_array

%token tLAST_TOKEN
Index: vm.c

--- vm.c (revision 22030)
+++ vm.c (working copy)
@@ -1825,4 +1825,36 @@ nsdr(void)
}

+static VALUE
+check_rescue_arg(VALUE klass)
+{

  • if (!rb_obj_is_kind_of(klass, rb_cModule)) {
  • VALUE args[3];
  • args[0] = rb_eTypeError;
  • args[1] = rb_str_new2("class or module required for rescue clause");
  • args[2] = vm_backtrace(GET_THREAD(), 0);
  • rb_exc_raise(rb_make_exception(sizeof(args) / sizeof(args[0]), args));
  • }
  • return klass;
    +}

+static VALUE
+m_core_handle_rescue_single(VALUE self, VALUE klass, VALUE exc)
+{

  • check_rescue_arg(klass);
  • return rb_funcall(klass, idEqq, 1, exc);
    +}

+static VALUE
+m_core_handle_rescue_array(VALUE self, VALUE klass, VALUE ary)
+{

  • long i;
  • check_rescue_arg(klass);
  • for (i = 0; i < RARRAY_LEN(ary); ++i) {
  • VALUE result = rb_funcall(klass, idEqq, 1, RARRAY_PTR(ary)[i]);
  • if (RTEST(result)) return result;
  • }
  • return Qfalse;
    +}

void
Init_VM(void)
@@ -1846,4 +1878,6 @@ Init_VM(void)
rb_define_method_id(klass, id_core_define_singleton_method, m_core_define_singleton_method, 3);
rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 1);

  • rb_define_method_id(klass, id_core_handle_rescue_single, m_core_handle_rescue_single, 2);
  • rb_define_method_id(klass, id_core_handle_rescue_array, m_core_handle_rescue_array, 2);
    rb_obj_freeze(fcore);
    rb_gc_register_mark_object(fcore);

--
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
中田 伸悦

=end

Actions #2

Updated by matz (Yukihiro Matsumoto) over 16 years ago

=begin
まつもと ゆきひろです

In message "Re: [ruby-dev:37903] Re: [Bug #1105] Ruby1.9でのrescue節の例外ハンドラのマッチの処理"
on Wed, 4 Feb 2009 20:21:21 +0900, Nobuyoshi Nakada writes:

|At Wed, 4 Feb 2009 16:45:09 +0900,
|Tatsuji Kawai wrote in [ruby-dev:37898]:
|> Ruby1.9とRuby1.8では、例外ハンドルクラスのリストにExceptionのサブ
|> クラス以外のオブジェクトが含まれている場合の挙動に違いがあります。
|
|これでどうでしょうか。

ささだくんがよければコミットしてください。

=end

Actions #3

Updated by ko1 (Koichi Sasada) over 16 years ago

=begin
 ささだです.

Nobuyoshi Nakada wrote::

+static VALUE
+m_core_handle_rescue_single(VALUE self, VALUE klass, VALUE exc)
+{

  • check_rescue_arg(klass);
  •  check_rescue_arg(exc);
    
  • return rb_funcall(klass, idEqq, 1, exc);
    +}

+static VALUE
+m_core_handle_rescue_array(VALUE self, VALUE klass, VALUE ary)
+{

  • long i;
  • check_rescue_arg(klass);
  • for (i = 0; i < RARRAY_LEN(ary); ++i) {
  •    VALUE exc = RARRAY_PTR(ary)[i];
    
  •    check_rescue_arg(exc);
    
  • VALUE result = rb_funcall(klass, idEqq, 1, exc);
  • if (RTEST(result)) return result;
  • }
  • return Qfalse;
    +}

 じゃなくていいんでしたっけ.つまり,投げられたほうじゃなくて,受ける方
をチェック.メソッド呼び出しが一回増えるのが,性能的にどの程度 impact が
あるのかよくわからないのですが.

そもそも,これは以前まつもとさんに「この仕様でいいですかね」と確認を

とったんだけどなぁ.

=> [yarv-dev:175] Re: eval in rescue clause

--
// SASADA Koichi at atdot dot net

=end

Actions #4

Updated by matz (Yukihiro Matsumoto) over 16 years ago

=begin
まつもと ゆきひろです

In message "Re: [ruby-dev:37922] Re: [Bug #1105] Ruby1.9でのrescue節の例外ハンドラのマッチの処理"
on Thu, 5 Feb 2009 23:58:56 +0900, SASADA Koichi writes:

|# そもそも,これは以前まつもとさんに「この仕様でいいですかね」と確認を
|# とったんだけどなぁ.
|# => [yarv-dev:175] Re: eval in rescue clause

おお、すっかり忘れてました。
それならそれで、rejectしても構いません。

仕様としては「raiseにはExceptionのサブクラスが必要、rescueで
は===によるチェックを行う(ただしExceptionかどうかののチェック
を含んでも構わない)」くらいでしょうかね。> 関係者

=end

Actions #5

Updated by yugui (Yuki Sonoda) almost 16 years ago

  • Status changed from Open to Rejected

=begin

=end

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0