From: Satoshi Shiba Date: 2010-05-22T02:15:20+09:00 Subject: [ruby-dev:41388] Re: [Bug #3295] make test aborted 芝と申します。 Fiber のパッチの実装を主に行った者です。 > kosakiです > > 現象: make test 不可能 > 原因: 高速化目的パッチ > > なので、「今」revertして1.9.3送りを提案します。5/Eぎりぎりに > make test出来るようになったとして、隠れていた別のバグが表に出てくる > 可能性がありますよね? 今回、Ubuntu-10.0.4 環境で Fiber が原因で Abort するのは Ubuntu-10.0.4で は、最適化オプションを O3 としたときに __longjmp_chk という関数を使用す るためのようです。 (O0 のときは _longjmp が使用されるようです。そのため、cont.c を O0 でコ ンパイルすると、make test に通ります。) __longjmp_chk は、以下のような処理を行います。 void __longjmp_chk(jmp_buf env, int val) { if (ジャンプ先のスタックが、現在のスタックに対してスタックの伸びてい く方向にある) { stack_t oss; sigaltstack(NULL, &oss); if (oss.ss_flags != SS_ONSTACK) { /* 現在動作中のスタックがシグナルスタックとして */ /* 宣言されているものではなかったら、エラー */ abort("longjmp causes uninitialized stack frame"); } } 従来の longjmp } つまり、__longjmp_chk 時にジャンプ先のスタックが現在のスタックに対してス タックの伸びていく方向にある場合は、現在動いているスタックが sigaltstack によって設定されたシグナルスタックでない限り、エラーとみなされるというこ とです。 そのため、set/longjmp でスタックを切り替える、今問題となっている Fiberの 実装では Ubuntu-10.0.4 の環境だと abort してしまいます。 set/longjmp ではなく、swapcontext を使用する実装に直したところ、make- test に通りました(本メールの末尾にパッチを張ります)。 以上のように、今回 make test で Fiber が原因で abort するのは、Fiber の 実装にバグがあるというよりも、使用するライブラリの仕様が変わってしまった ことが原因だと思います。 しかし、Fiber のパッチが trunk に取り込まれたのが最近であり、まだテスト が十分であるとはいえないため、小崎さんのおっしゃるとおり、隠れているバグ が潜んでいる可能性は十分にあると思います。 そのため、revertして Fiber のパッチを 1.9.3送りにするという提案に、私も 賛成します。 Fiber のパッチを、trunk にてテストさせていただきたいです。 ご検討、よろしくお願いします。 Index: cont.c =================================================================== --- cont.c (revision 27947) +++ cont.c (working copy) @@ -621,16 +621,7 @@ fiber_setcontext(rb_fiber_t *newfib, rb_ #ifdef _WIN32 SwitchToFiber(newfib->fib_handle); #else - if (!ruby_setjmp(oldfib->cont.jmpbuf)) { - if (newfib->status != RUNNING) { - if (setcontext(&newfib->context) < 0) { - rb_bug("context switch between fiber failed"); - } - } - else { - ruby_longjmp(newfib->cont.jmpbuf, 1); - } - } + swapcontext(&oldfib->context, &newfib->context); #endif } #endif