遠藤です。

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 <main>': $! is a read-only variable (NameError)
        from -e:1:in `<main>'


どうしたもんでしょうか。
以下はスタックトレースを出すようにし、$! への代入を許可するように
するパッチです。


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 <mame / tsg.ne.jp>