[#41278] [BUG:1.9] BINARY should not be ASCII-compatible — Yugui <yugui@...>

WXVndWkbJEIkRyQ5ISMbKEIKCgo+IBskQiRHISIkKiQqJGAkTSQzJDMkXiRHJE41RE9AJEclKyVQ

15 messages 2010/05/11

[#41407] [Bug #3339] win32ole test failure — Usaku NAKAMURA <redmine@...>

Bug #3339: win32ole test failure

20 messages 2010/05/25
[#41411] Re: [Bug #3339] win32ole test failure — Masaki Suketa <masaki.suketa@...> 2010/05/25

助田です。

[#41412] Re: [Bug #3339] win32ole test failure — "U.Nakamura" <usa@...> 2010/05/25

こんにちは、なかむら(う)です。

[ruby-dev:41388] Re: [Bug #3295] make test aborted

From: Satoshi Shiba <shiba@...>
Date: 2010-05-21 17:15:20 UTC
List: ruby-dev #41388
芝と申します。

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

In This Thread