From: Yusuke ENDOH Date: 2008-05-26T22:30:59+09:00 Subject: [ruby-dev:34855] interrupt while raising an exception terminates the program with no error print 遠藤です。 raise 実行中に SIGINT で割り込んだとき、高確率で何も言わずに 異常終了します。 $ ./ruby -ve 'begin; raise; rescue; retry; end' ruby 1.9.0 (2008-05-26 revision 16615) [i686-linux] ^C $ echo $? 1 $ ./ruby -ve 'while true; raise rescue nil; end' ruby 1.9.0 (2008-05-26 revision 16615) [i686-linux] ^C $ echo $? 1 これは仕様でしょうか。 返り値が 1 になってるから気づけ、ということかもしれませんが、 気づきにくいし原因がわからないので嬉しくないです。 この現象は 2 つの問題から成るようです。 - rb_longjmp が呼ばれてから JUMP_TAG するまでに割り込みが 発生したとき [FATAL] exception reentered になってしまう - [FATAL] exception reentered でエラーが表示されない 前者は普通のプログラムでもたまに起きそうなんですが、どう対処 したものかわかりません。割り込み処理を遅延するフラグが必要? 後者は多分以下でなんとかなると思います。error_print は例外の 発生に気を使いまくってるようなので大丈夫そうだと思いましたが、 [ruby-core:1122] のように例外で再帰して SEGV するような例が あったらすみません。 $ ./ruby -ve 'begin; raise; rescue; retry; end' ruby 1.9.0 (2008-05-26 revision 16615) [i686-linux] :17: exception reentered (fatal) Index: eval_error.c =================================================================== --- eval_error.c (revision 16615) +++ eval_error.c (working copy) @@ -215,8 +215,6 @@ int status = EXIT_FAILURE; rb_thread_t *th = GET_THREAD(); - if (rb_thread_set_raised(th)) - return EXIT_FAILURE; switch (ex & TAG_MASK) { case 0: status = EXIT_SUCCESS; @@ -247,8 +245,7 @@ error_pos(); warn_printf(": unexpected throw\n"); break; - case TAG_RAISE: - case TAG_FATAL: { + case TAG_RAISE: { VALUE errinfo = GET_THREAD()->errinfo; if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) { status = sysexit_status(errinfo); @@ -261,6 +258,9 @@ } break; } + case TAG_FATAL: + error_print(); + break; default: rb_bug("Unknown longjmp status %d", ex); break; -- Yusuke ENDOH