https://redmine.ruby-lang.org/
https://redmine.ruby-lang.org/favicon.ico?1711330511
2010-11-05T21:49:34Z
Ruby Issue Tracking System
Ruby master - Bug #4027: Signal.trap で busy loop に陥る
https://redmine.ruby-lang.org/issues/4027?journal_id=14051
2010-11-05T21:49:34Z
nagachika (Tomoyuki Chikanaga)
nagachika00@gmail.com
<ul></ul><p>=begin<br>
残念ながら signal_buff を increment しているところを rb_disable_interrupt()/rb_enable_interrupt() でくくってみた実行体でも再現しました。<br>
ただ今回は signal_buff.size = -1 ではなくて 1 で逆に余分に increment されたようです。</p>
<p>(gdb) p signal_buff<br>
$1 = {cnt = {0 <repeats 65 times>}, size = 1}</p>
<p>=end</p>
Ruby master - Bug #4027: Signal.trap で busy loop に陥る
https://redmine.ruby-lang.org/issues/4027?journal_id=14052
2010-11-05T22:05:15Z
ko1 (Koichi Sasada)
<ul></ul><p>=begin<br>
(2010/11/05 12:49), Tomoyuki Chikanaga wrote:</p>
<blockquote>
<p>チケット <a class="issue tracker-1 status-6 priority-4 priority-default closed parent" title="Bug: Signal.trap で busy loop に陥る (Rejected)" href="https://redmine.ruby-lang.org/issues/4027">#4027</a> が更新されました。 (by Tomoyuki Chikanaga)</p>
<p>残念ながら signal_buff を increment しているところを rb_disable_interrupt()/rb_enable_interrupt() でくくってみた実行体でも再現しました。<br>
ただ今回は signal_buff.size = -1 ではなくて 1 で逆に余分に increment されたようです。</p>
<p>(gdb) p signal_buff<br>
$1 = {cnt = {0 <repeats 65 times>}, size = 1}</p>
</blockquote>
<p> ちょっと、状況を見ないで返信しますが、シグナルハンドラ側で何かする必要<br>
は無くて、rb_get_next_signal() 側で rb_disable_interrupt する必要があり<br>
ます。... が、もうなってますね。なぜ、こういう事象が起こるんだろう。</p>
<p> というか、rb_get_next_signal() で rb_enable_interrpt() して、シグナル<br>
マスクを全部外しているのは、とてもまずいような。というか、メインスレッド<br>
のシグナルマスクが外れているのはこれが理由か...?</p>
<p>--<br>
// SASADA Koichi at atdot dot net<br>
=end</p>
Ruby master - Bug #4027: Signal.trap で busy loop に陥る
https://redmine.ruby-lang.org/issues/4027?journal_id=14053
2010-11-05T22:05:18Z
ko1 (Koichi Sasada)
<ul></ul><p>=begin<br>
(2010/11/05 12:49), Tomoyuki Chikanaga wrote:</p>
<blockquote>
<p>チケット <a class="issue tracker-1 status-6 priority-4 priority-default closed parent" title="Bug: Signal.trap で busy loop に陥る (Rejected)" href="https://redmine.ruby-lang.org/issues/4027">#4027</a> が更新されました。 (by Tomoyuki Chikanaga)</p>
<p>残念ながら signal_buff を increment しているところを rb_disable_interrupt()/rb_enable_interrupt() でくくってみた実行体でも再現しました。<br>
ただ今回は signal_buff.size = -1 ではなくて 1 で逆に余分に increment されたようです。</p>
<p>(gdb) p signal_buff<br>
$1 = {cnt = {0 <repeats 65 times>}, size = 1}</p>
</blockquote>
<p> ちょっと、状況を見ないで返信しますが、シグナルハンドラ側で何かする必要<br>
は無くて、rb_get_next_signal() 側で rb_disable_interrupt する必要があり<br>
ます。... が、もうなってますね。なぜ、こういう事象が起こるんだろう。</p>
<p> というか、rb_get_next_signal() で rb_enable_interrpt() して、シグナル<br>
マスクを全部外しているのは、とてもまずいような。というか、メインスレッド<br>
のシグナルマスクが外れているのはこれが理由か...?</p>
<p>--<br>
// SASADA Koichi at atdot dot net</p>
<p>=end</p>
Ruby master - Bug #4027: Signal.trap で busy loop に陥る
https://redmine.ruby-lang.org/issues/4027?journal_id=14067
2010-11-06T21:55:27Z
nagachika (Tomoyuki Chikanaga)
nagachika00@gmail.com
<ul></ul><p>=begin</p>
<blockquote>
<p>というか、rb_get_next_signal() で rb_enable_interrpt() して、シグナル<br>
マスクを全部外しているのは、とてもまずいような。というか、メインスレッド<br>
のシグナルマスクが外れているのはこれが理由か...?<br>
たしかに rb_enable_interrupt() では問答無用で全てのシグナルマスクを外していますね。<br>
直前のものに復旧したほうがいいでしょうか。<br>
また rb_disable_interrupt() では SIGSEGV と SIGVTALRM はマスクしていないですが、ブロックするような処理をしているわけでもないので SIGVTALRM はマスクしていいのではないでしょうか。</p>
</blockquote>
<p>今は問題の環境を触れないので、月曜日になったらこのあたり変更して再度やってみます。</p>
<p>=end</p>
Ruby master - Bug #4027: Signal.trap で busy loop に陥る
https://redmine.ruby-lang.org/issues/4027?journal_id=14117
2010-11-11T01:33:21Z
nagachika (Tomoyuki Chikanaga)
nagachika00@gmail.com
<ul><li><strong>File</strong> <a href="/attachments/1301">sigmask.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/1301/sigmask.patch">sigmask.patch</a> added</li></ul><p>=begin<br>
元々の signal_buff の数が合わなくないのはまだ原因がわかりませんが、<br>
シグナルマスクの処理について調べていて間違っていそうなところをみつけました。</p>
<p>まずささださんが指摘されていた rb_get_next_signal() で rb_enable_interrupt() でシグナルマスクを<br>
外している点ですが、rb_get_next_signal() はタイマースレッドからのみ呼ばれるのでこれは問題なさそうです。</p>
<p>しかしメインスレッドその他の Thread に対応するスレッドのシグナルマスクは SIGSEGV と SIGVTALRM のみ<br>
外されているはずなのに、全て外されていました。<br>
このため sighandler() がタイマースレッドでなくメインスレッドで実行されています。<br>
これは以下のような流れでおきています。</p>
<ul>
<li>init_sigchld で初期状態(空マスク)の sigmask が trap_last_sigmask に保存される</li>
<li>タイマースレッドの起動(rb_thread_create_timer_thread)でメインスレッドはマスクがセットされる</li>
<li>その後ファイルロード中に例外が生成された時に rb_trap_restore_mask() が呼ばれて trap_last_sigmask に<br>
保存された空マスクがセットされるためシグナルマスクが外れる</li>
</ul>
<p>また、Signal.trap でハンドラをセットした時に、そのシグナルのシグナルマスクが外されています。<br>
sigaction によるシグナルハンドラの実行はタイマースレッドにまかせているはずなのでこれは不要だと思います。<br>
また例外発生時に rb_trap_restore_mask を読んでいるのも、trap() で例外が発生しても trap_ensure() で<br>
シグナルマスクを戻す処理は行なわれているので不要なような気がします。元々どういう理由で呼ばれているのか<br>
わからなかったので自信ないですけど。</p>
<p>というわけで添付のようなパッチを作成してみました。</p>
<p>ところがこれを当てると make test-all で Failure が 2つ増えます。<br>
いずれも ruby のプロセスをシグナルで止めた時に終了ステータスが $?.signaled? == true でなく<br>
$?.exited? == true になるためです。<br>
これはどう直せばいいのかわかりません。</p>
<ol>
<li>
<p>Failure:<br>
test_should_propagate_signaled(TestBeginEndBlock) [/Users/nagachika/opt/ruby-trunk/src/ruby-trunk/test/ruby/test_beginendblock.rb:108]:<br>
Expected 0 to be nil.</p>
</li>
<li>
<p>Failure:<br>
test_status_kill(TestProcess) [/Users/nagachika/opt/ruby-trunk/src/ruby-trunk/test/ruby/test_process.rb:1073]:<br>
[s.exited?, s.signaled?, s.stopped?].<br>
<[false, true, false]> expected but was<br>
<[true, false, false]>.</p>
</li>
</ol>
<p>また、sighandler() がメインスレッドから呼ばれるのは Process.spawn を実行するとまだおきてしまいます。<br>
process.c の before_fork/after_fork で fork の時に一時的にタイマースレッドを止めてシグナルマスクを外すためです。<br>
こちらもどうしていいものかわからないです。<br>
fork してそのまま動き続けるようなものはどうしようもないような気がしますが、spawn するものは<br>
fork 後に sigprogmask で外すようにするなどでなんとかならないものでしょうか。<br>
あーでもタイマースレッドの再起動で結局一時的に外してしまいますね……</p>
<p>なお、このせいで sighandler にメインスレッドとタイマースレッドで同時に実行してしまって<br>
signal_buff のカウンタがおかしくなったのかも、とも思ったのですが、ATOMIC_INC 部分を disassemble してみると<br>
それぞれ incl の1命令で実行されているので、仮に並列に実行されても加算もれすることはなさそうです。<br>
プロセッサによってはダメだったりするんでしょうか。</p>
<p>=end</p>
Ruby master - Bug #4027: Signal.trap で busy loop に陥る
https://redmine.ruby-lang.org/issues/4027?journal_id=14125
2010-11-11T10:47:17Z
nagachika (Tomoyuki Chikanaga)
nagachika00@gmail.com
<ul></ul><p>=begin</p>
<blockquote>
<p>なお、このせいで sighandler にメインスレッドとタイマースレッドで同時に実行してしまって<br>
signal_buff のカウンタがおかしくなったのかも、とも思ったのですが、ATOMIC_INC 部分を disassemble してみると<br>
それぞれ incl の1命令で実行されているので、仮に並列に実行されても加算もれすることはなさそうです。<br>
これは勘違いしていて、lock prefix がついていないので複数コアで並列に実行されると問題かもしれません。<br>
そして r29589 で gcc-4 の builtin function を使う修正が入っていたのを思い出したので<br>
CC=gcc-4.4 にしてコンパイルしなおしたら ATOMIC_INC は</p>
</blockquote>
<p>80e1b93: f0 80 00 01 lock addb $0x1,(%eax)<br>
80e1b97: f0 80 05 81 ef 1f 08 lock addb $0x1,0x81fef81</p>
<p>のように lock prefix 付きになったので、これで大丈夫だと思います。<br>
=end</p>
Ruby master - Bug #4027: Signal.trap で busy loop に陥る
https://redmine.ruby-lang.org/issues/4027?journal_id=14126
2010-11-11T10:51:09Z
ko1 (Koichi Sasada)
<ul></ul><p>=begin<br>
ささだです。</p>
<p> シグナルに関しての調査、ありがとうございます。近いうちに反映させます。</p>
<p>(2010/11/11 10:47), Tomoyuki Chikanaga wrote:</p>
<blockquote>
<p>これは勘違いしていて、lock prefix がついていないので複数コアで並列に実行されると問題かもしれません。<br>
そして r29589 で gcc-4 の builtin function を使う修正が入っていたのを思い出したので<br>
CC=gcc-4.4 にしてコンパイルしなおしたら ATOMIC_INC は</p>
<p>80e1b93: f0 80 00 01 lock addb $0x1,(%eax)<br>
80e1b97: f0 80 05 81 ef 1f 08 lock addb $0x1,0x81fef81</p>
</blockquote>
<p> ちなみに、以前はどのコンパイラを利用されていたでしょうか。</p>
<p>--<br>
// SASADA Koichi at atdot dot net</p>
<p>=end</p>
Ruby master - Bug #4027: Signal.trap で busy loop に陥る
https://redmine.ruby-lang.org/issues/4027?journal_id=14127
2010-11-11T11:34:03Z
nagachika (Tomoyuki Chikanaga)
nagachika00@gmail.com
<ul></ul><p>=begin</p>
<blockquote>
<p>ちなみに、以前はどのコンパイラを利用されていたでしょうか。<br>
gcc 3.4.6 でした。 gcc -v を貼ります。</p>
</blockquote>
<p>$ gcc -v<br>
/usr/local/lib/gcc/i686-pc-linux-gnu/3.4.6/specs から spec を読み込み中<br>
コンフィグオプション: ./configure --program-suffix=-3.4.6 --disable-shared --disable-ada --disable-java --disable-objc : (reconfigured) ./configure --program-suffix=-3.4.6 --disable-shared --enable-languages=c,c++,fortran : (reconfigured) ./configure --program-suffix=-3.4.6 --disable-shared --enable-languages=c,c++,fortran : (reconfigured) ./configure --program-suffix=-3.4.6 --disable-shared --enable-languages=c,c++,f77<br>
スレッドモデル: posix<br>
gcc version 3.4.6</p>
<p>=end</p>
Ruby master - Bug #4027: Signal.trap で busy loop に陥る
https://redmine.ruby-lang.org/issues/4027?journal_id=17251
2011-05-26T23:55:58Z
nagachika (Tomoyuki Chikanaga)
nagachika00@gmail.com
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Rejected</i></li></ul><p>シグナルマスクに関しては <a class="issue tracker-1 status-5 priority-4 priority-default closed child" title="Bug: signal が正しくマスクされておらず main thread でシグナルハンドラが動いている (Closed)" href="https://redmine.ruby-lang.org/issues/4765">#4765</a> に分離されました。<br>
signal_buff の競合状態は、新しめの gcc や Windows だと ATOMIC_INC/ATOMIC_DEC がロックつきになることと、<br>
<a class="issue tracker-1 status-5 priority-4 priority-default closed child" title="Bug: signal が正しくマスクされておらず main thread でシグナルハンドラが動いている (Closed)" href="https://redmine.ruby-lang.org/issues/4765">#4765</a> でシグナルハンドラの実行がタイマースレッドに限定されれば発生しなくなるはずなのでこちらは閉じます。</p>