[#39420] Marshal.load で例外発生時に Segmentation fault エラー — patamanta@...
金田有二と申します。
5 messages
2009/10/02
[#39421] exception from open-uri — Yusuke ENDOH <mame@...>
遠藤です。
5 messages
2009/10/03
[#39439] [Bug #2179] 1.9.2において block のスコープがおかしいときがある — 益隆 三村 <redmine@...>
Bug #2179: 1.9.2において block のスコープがおかしいときがある
4 messages
2009/10/06
[#39446] Is the maintainer discharging rule approved? and about matrix.rb — Yugui <yugui@...>
Yuguiです。
4 messages
2009/10/08
[#39451] getaddrinfo: Name or service not known (SocketError) in net/ftp — Tanaka Akira <akr@...>
boron で気がついたのですが、net/ftp で login のときに
4 messages
2009/10/09
[#39469] Re: getaddrinfo: Name or service not known (SocketError) in net/ftp
— Shugo Maeda <shugo@...>
2009/10/12
前田です。
[#39453] [BUG: trunk] GC mark bug — SASADA Koichi <ko1@...>
ささだです.
7 messages
2009/10/10
[#39501] [bug:trunk] invalid memory access in 100**900 — Tanaka Akira <akr@...>
以下のように、100**900 を計算すると変なところをアクセスするようです。
4 messages
2009/10/17
[#39506] [Bug:1.9] case 文の式が省略され when 節に配列展開があるときの挙動 — wanabe <s.wanabe@...>
ワナベと申します。
4 messages
2009/10/17
[#39533] [Bug #2263] typo in man/ruby.1 — Narihiro Nakamura <redmine@...>
Bug #2263: typo in man/ruby.1
11 messages
2009/10/24
[#39534] Re: [Bug #2263] typo in man/ruby.1
— Yusuke ENDOH <mame@...>
2009/10/24
遠藤です。
[#39548] [Bug #2291] Net::FTPでソケットをオープンする前にbinary=を呼び出すと落ちる — Akira Matsuda <redmine@...>
Bug #2291: Net::FTPでソケットをオープンする前にbinary=を呼び出すと落ちる
10 messages
2009/10/27
[#39578] [Bug #2308] セーフレベル1の場合、Net::IMAPでSecurityErrorが発生する — Nozomu Kurasawa <redmine@...>
Bug #2308: セーフレベル1の場合、Net::IMAPでSecurityErrorが発生する
5 messages
2009/10/30
[#39579] [Bug #2310] should ensure GVL_UNLOCK_END in rb_thread_blocking_region — _ wanabe <redmine@...>
Bug #2310: should ensure GVL_UNLOCK_END in rb_thread_blocking_region
4 messages
2009/10/30
[#39584] Re: [ruby-cvs:32774] Ruby:r25556 (trunk): * array.c (rb_ary_to_ary): do not use #respond_to? to detect — Nobuyoshi Nakada <nobu@...>
なかだです。
6 messages
2009/10/30
[#39585] Re: [ruby-cvs:32774] Ruby:r25556 (trunk): * array.c (rb_ary_to_ary): do not use #respond_to? to detect
— Yukihiro Matsumoto <matz@...>
2009/10/30
まつもと ゆきひろです
[#39589] Re: [ruby-cvs:32774] Ruby:r25556 (trunk): * array.c (rb_ary_to_ary): do not use #respond_to? to detect
— Yukihiro Matsumoto <matz@...>
2009/10/30
まつもと ゆきひろです
[#39591] Re: [ruby-cvs:32774] Ruby:r25556 (trunk): * array.c (rb_ary_to_ary): do not use #respond_to? to detect
— Nobuyoshi Nakada <nobu@...>
2009/10/30
なかだです。
[#39592] infinite recursive call to C function — Yusuke ENDOH <mame@...>
遠藤です。
17 messages
2009/10/30
[#39596] Re: infinite recursive call to C function
— Yukihiro Matsumoto <matz@...>
2009/10/30
まつもと ゆきひろです
[#39599] Re: infinite recursive call to C function
— Nobuyoshi Nakada <nobu@...>
2009/11/02
なかだです。
[#39601] Re: infinite recursive call to C function
— Yukihiro Matsumoto <matz@...>
2009/11/02
まつもと ゆきひろです
[#39602] Re: infinite recursive call to C function
— Nobuyoshi Nakada <nobu@...>
2009/11/02
なかだです。
[#39603] Re: infinite recursive call to C function
— Yukihiro Matsumoto <matz@...>
2009/11/02
まつもと ゆきひろです
[#39605] Re: infinite recursive call to C function
— Nobuyoshi Nakada <nobu@...>
2009/11/02
なかだです。
[#39608] Re: infinite recursive call to C function
— Yukihiro Matsumoto <matz@...>
2009/11/02
まつもと ゆきひろです
[#39609] Re: infinite recursive call to C function
— Nobuyoshi Nakada <nobu@...>
2009/11/02
なかだです。
[#39610] Re: infinite recursive call to C function
— Yukihiro Matsumoto <matz@...>
2009/11/02
まつもと ゆきひろです
[ruby-dev:39595] Re: [ruby-cvs:32774] Ruby:r25556 (trunk): * array.c (rb_ary_to_ary): do not use #respond_to? to detect
From:
Yukihiro Matsumoto <matz@...>
Date:
2009-10-30 14:41:53 UTC
List:
ruby-dev #39595
まつもと ゆきひろです
In message "Re: [ruby-dev:39594] Re: [ruby-cvs:32774] Ruby:r25556 (trunk): * array.c (rb_ary_to_ary): do not use #respond_to? to detect"
on Fri, 30 Oct 2009 23:10:15 +0900, Yukihiro Matsumoto <matz@ruby-lang.org> writes:
| * 私の理解が正しければ、正しい(と思われる)ロジックは
|
| + meがあればそれを呼ぶ
| + method_missingが再定義されていなければQundef
| + 再定義されていれば、rescueした上でmethod_missingを呼ぶ
| + 例外が起きたら、以下の条件を満たすときだけ、Qundef。
| 満たさなければ、同じ例外をそのままあげる
| - レシーバが同じ
| - メソッド名が同じ
|
|どうでしょう?
この方針に従い、こんなパッチを作ってみました。添付のようなプ
ログラムを実行すると挙動の違いがわかるかもしれません。
diff --git a/vm_eval.c b/vm_eval.c
index 86aa52e..c749d1d 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -117,7 +117,7 @@ vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv,
RB_GC_GUARD(new_args);
rb_ary_unshift(new_args, ID2SYM(id));
- return rb_funcall2(recv, rb_intern("method_missing"),
+ return rb_funcall2(recv, idMethodMissing,
argc+1, RARRAY_PTR(new_args));
}
case VM_METHOD_TYPE_OPTIMIZED: {
@@ -201,7 +201,7 @@ stack_check(void)
}
}
-static inline rb_method_entry_t *rb_search_method_emtry(VALUE recv, ID mid);
+static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid);
static inline int rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self);
#define NOEX_OK NOEX_NOSUPER
@@ -223,7 +223,7 @@ static inline VALUE
rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
call_type scope, VALUE self)
{
- rb_method_entry_t *me = rb_search_method_emtry(recv, mid);
+ rb_method_entry_t *me = rb_search_method_entry(recv, mid);
rb_thread_t *th = GET_THREAD();
int call_status = rb_method_call_status(th, me, scope, self);
@@ -234,41 +234,81 @@ rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
return vm_call0(th, recv, mid, argc, argv, me);
}
-VALUE
-rb_check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
+struct rescue_funcall_args {
+ VALUE recv;
+ VALUE sym;
+ int argc;
+ VALUE *argv;
+};
+
+static VALUE
+check_funcall_exec(struct rescue_funcall_args *args)
+{
+ VALUE new_args = rb_ary_new4(args->argc, args->argv);
+
+ RB_GC_GUARD(new_args);
+ rb_ary_unshift(new_args, args->sym);
+ return rb_funcall2(args->recv, idMethodMissing,
+ args->argc+1, RARRAY_PTR(new_args));
+}
+
+static VALUE
+check_funcall_failed(struct rescue_funcall_args *args, VALUE e)
+{
+ VALUE sym = rb_funcall(e, rb_intern("name"), 0, 0);
+
+ if (args->sym != sym)
+ rb_exc_raise(e);
+ return Qundef;
+}
+
+static VALUE
+check_funcall(rb_method_entry_t *me, VALUE recv, ID mid, int argc, VALUE *argv)
{
- rb_method_entry_t *me = rb_search_method_emtry(recv, mid);
rb_thread_t *th = GET_THREAD();
int call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef);
if (call_status != NOEX_OK) {
- return Qundef;
+ if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) {
+ return Qundef;
+ }
+ else {
+ struct rescue_funcall_args args;
+
+ args.recv = recv;
+ args.sym = ID2SYM(mid);
+ args.argc = argc;
+ args.argv = argv;
+ return rb_rescue2(check_funcall_exec, (VALUE)&args,
+ check_funcall_failed, (VALUE)&args,
+ rb_eNoMethodError, (VALUE)0);
+ }
}
stack_check();
return vm_call0(th, recv, mid, argc, argv, me);
}
VALUE
+rb_check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
+{
+ return check_funcall(rb_search_method_entry(recv, mid), recv, mid, argc, argv);
+}
+
+VALUE
rb_funcall_no_recursive(VALUE recv, ID mid, int argc, VALUE *argv, VALUE (*func)())
{
- rb_method_entry_t *me = rb_search_method_emtry(recv, mid);
- rb_thread_t *th = GET_THREAD();
+ rb_method_entry_t *me = rb_search_method_entry(recv, mid);
int call_status;
if (!me) return Qundef;
if (me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
me->def->body.cfunc.func == func)
return Qundef;
- call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef);
- if (call_status != NOEX_OK) {
- return Qundef;
- }
- stack_check();
- return vm_call0(th, recv, mid, argc, argv, me);
+ return check_funcall(me, recv, mid, argc, argv);
}
static inline rb_method_entry_t *
-rb_search_method_emtry(VALUE recv, ID mid)
+rb_search_method_entry(VALUE recv, ID mid)
{
VALUE klass = CLASS_OF(recv);
Attachments (1)
sample.rb
(216 Bytes, text/x-ruby)
class A
include Comparable
def <=>(b)
self.object_id <=> b.object_id
end
def method_missing(s, *a)
if s == :to_str
foo(5)
"8"
else
super
end
end
end
p (A.new.."9").to_a