永井@知能.九工大です.

rb_rescue2() がうまく働いてくれなくて,
ちょっと「謎」な状況に困ってます.

今,次のような拡張ライブラリがあったとします.
---------------------------------------------------------------
#include "ruby.h"

VALUE
hoge_raise(self)
    VALUE self;
{
    fprintf(stderr, "call hoge_raise\n");
    rb_raise(rb_eArgError, "hoge raise");
    return Qnil; /* dummy */
}

VALUE
hoge_rescue(self)
    VALUE self;
{
    fprintf(stderr, "call hoge_rescue\n");
    return Qnil;
}

VALUE
hoge1(self)
    VALUE self;
{
    return rb_rescue(hoge_raise, self, 
                     hoge_rescue, self);
}

VALUE
hoge2(self)
    VALUE self;
{
    return rb_rescue2(hoge_raise, self, 
                      hoge_rescue, self, 
                      rb_eArgError, (VALUE)0);
}

VALUE
hoge3(self)
    VALUE self;
{
    return rb_rescue2(hoge_raise, self, 
                      hoge_rescue, self, 
                      rb_eStandardError, (VALUE)0);
}

VALUE
hoge4(self)
    VALUE self;
{
    VALUE e;

    e = rb_const_get(rb_cObject, rb_intern("ArgumentError"));
    fprintf(stderr, "%lx %lx\n", rb_eArgError, e);
    return rb_rescue2(hoge_raise, self, 
                      hoge_rescue, self, 
                      e, (VALUE)0);
}

void
Init_hoge()
{
    rb_define_method(rb_cObject, "hoge1", hoge1, 0);
    rb_define_method(rb_cObject, "hoge2", hoge2, 0);
    rb_define_method(rb_cObject, "hoge3", hoge3, 0);
    rb_define_method(rb_cObject, "hoge4", hoge4, 0);
}
---------------------------------------------------------------

この場合,hoge1 〜 hoge4 のいずれも hoge_raise と hoge_rescue とを
呼んで nil を返すはずだと思うのですが,そうなってくれません.
次のようになり,rb_rescue2() が例外を捉えていないようです.

---------------------------------------------------------------
% /usr/local/bin/irb
irb(main):001:0> require './hoge.so'
=> true
irb(main):002:0> hoge1
call hoge_raise
call hoge_rescue
=> nil
irb(main):003:0> hoge2
call hoge_raise
ArgumentError: hoge raise
        from (irb):3:in `hoge2'
        from (irb):3
        from :0
irb(main):004:0> hoge3
call hoge_raise
ArgumentError: hoge raise
        from (irb):4:in `hoge3'
        from (irb):4
        from :0
irb(main):005:0> hoge4
401e2404 401e2404
call hoge_raise
ArgumentError: hoge raise
        from (irb):5:in `hoge4'
        from (irb):5
        from :0
irb(main):006:0> 
---------------------------------------------------------------

eval.c での rb_rescue() の定義は

---------------------------------------------------------------
VALUE
rb_rescue(b_proc, data1, r_proc, data2)
    VALUE (*b_proc)(), (*r_proc)();
    VALUE data1, data2;
{
    return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError, (VALUE)0);
}
---------------------------------------------------------------

ですから,hoge1 は OK で hoge3 がダメというのもよくわかりません.
ruby -v の結果は "ruby 1.8.3 (2005-08-29) [i686-linux]" です.
いつからこのような状況になったのかはわかりませんが,
なにか心当たりはありますでしょうか?

もし私の手元だけでの異常となれば,それはそれで別の調査ができますので
よろしくお願いします.
-- 
                                       永井 秀利 (九工大 知能情報)
                                           nagai / ai.kyutech.ac.jp