From: Yusuke ENDOH Date: 2008-10-13T17:41:24+09:00 Subject: [ruby-dev:36712] abort in rescue 遠藤です。 1.8 では rescue の中で abort するとスタックトレースを出すようですが、 1.9 では何も表示されなくなっています。 $ ruby18 -e 'begin; raise; rescue; abort; end' -e:1: unhandled exception $ ruby19 -e 'begin; raise; rescue; abort; end' rb_f_abort を見るとスタックトレースを出そうとするコードが残っており、 意図的な挙動変更には見えませんでした。 スタックトレースを出すようにするのは簡単ですが、1.9 では $! = nil が 禁止されているため、この挙動を抑止する方法がありません。 $ ruby18 -e 'begin; raise; rescue; $! = nil; abort; end' $ ruby19 -e 'begin; raise; rescue; $! = nil; abort; end' -e:1:in `rescue in
': $! is a read-only variable (NameError) from -e:1:in `
' どうしたもんでしょうか。 以下はスタックトレースを出すようにし、$! への代入を許可するように するパッチです。 Index: eval.c =================================================================== --- eval.c (revision 19769) +++ eval.c (working copy) @@ -426,7 +426,7 @@ rb_raise(rb_eInterrupt, "%s", ""); } -static VALUE get_errinfo(void); +VALUE get_errinfo(void); /* * call-seq: @@ -953,7 +953,7 @@ return 0; } -static VALUE +VALUE get_errinfo(void) { VALUE *ptr = errinfo_place(); @@ -971,7 +971,6 @@ return get_errinfo(); } -#if 0 static void errinfo_setter(VALUE val, ID id, VALUE *var) { @@ -988,7 +987,6 @@ } } } -#endif VALUE rb_errinfo(void) @@ -1119,7 +1117,7 @@ Init_eval(void) { rb_define_virtual_variable("$@", errat_getter, errat_setter); - rb_define_virtual_variable("$!", errinfo_getter, 0); + rb_define_virtual_variable("$!", errinfo_getter, errinfo_setter); rb_define_global_function("iterator?", rb_f_block_given_p, 0); rb_define_global_function("block_given?", rb_f_block_given_p, 0); Index: process.c =================================================================== --- process.c (revision 19769) +++ process.c (working copy) @@ -2534,10 +2534,12 @@ rb_f_abort(int argc, VALUE *argv) { extern void ruby_error_print(void); + extern VALUE get_errinfo(void); rb_secure(4); if (argc == 0) { - if (!NIL_P(GET_THREAD()->errinfo)) { + VALUE errinfo = GET_THREAD()->errinfo = get_errinfo(); + if (!NIL_P(errinfo)) { ruby_error_print(); } rb_exit(EXIT_FAILURE); -- Yusuke ENDOH