Bug #7084
closedRubyVM::InstructionSequence.compile("1+"*10000 + "1") causes SystemStackError or Segmentation Fault
Description
以下のように ulimit -s の値に応じて stack level too deep と Segmentation Fault のどちらかが発生するようです。
$ .prefix/bin/ruby -v
ruby 2.0.0dev (2012-09-29 trunk 37053) [x86_64-darwin12.1.0]
$ ulimit -s
8192
$ .prefix/bin/ruby -e 'p RubyVM::InstructionSequence.compile("1+"*10000+"1")'
-e:1: stack level too deep (SystemStackError)
$ ulimit -s 32768
$ .prefix/bin/ruby -e 'p RubyVM::InstructionSequence.compile("1+"*10000+"1")'
-e:1: [BUG] Segmentation fault
ruby 2.0.0dev (2012-09-29 trunk 37053) [x86_64-darwin12.1.0]
-- Control frame information -----------------------------------------------
c:0003 p:---- s:0009 e:000008 CFUNC :compile
c:0002 p:0028 s:0005 e:000bc8 EVAL -e:1 [FINISH]
c:0001 p:0000 s:0002 e:0020e8 TOP [FINISH]
-e:1:in <main>' -e:1:in
compile'
-- C level backtrace information -------------------------------------------
See Crash Report log file under ~/Library/Logs/CrashReporter or
/Library/Logs/CrashReporter, for the more detail of.
-- Other runtime information -----------------------------------------------
-
Loaded script: -e
-
Loaded features:
Updated by mrkn (Kenta Murata) about 12 years ago
gdb で採取したバックとレースを gist に上げました。ulimit -s 8192 の場合です。参考までに。
https://gist.github.com/3803540
Updated by ko1 (Koichi Sasada) about 12 years ago
(2012/09/29 18:27), mrkn (Kenta Murata) wrote:
以下のように ulimit -s の値に応じて stack level too deep と Segmentation Fault のどちらかが発生するようです。
ええと,どうしたもんですかね.実装の都合でスタックオーバーフローするも
のは他にもありそうなので,これだけ頑張るべきか,よくわからないんですが....
これだけ取り出した理由はなんでしょうか.こういう操作ってよくやるんです
かね.
--
// SASADA Koichi at atdot dot net
Updated by mrkn (Kenta Murata) about 12 years ago
"1+"*10000 + "1" は YAPC::Asia の LT で見かけたネタです。
ulimit -s の値に依存して SEGV してしまう場合があるので、それだけでも直したいです。
Updated by ko1 (Koichi Sasada) about 12 years ago
(2012/09/29 23:11), mrkn (Kenta Murata) wrote:
ulimit -s の値に依存して SEGV してしまう場合があるので、それだけでも直したいです。
ulimit -s の値に依存せず SEGV するのはもっと嫌な気がしますが,それはと
もかく,直るのなら大変結構なことだと思います.よろしくお願いします.
--
// SASADA Koichi at atdot dot net
Updated by nobu (Nobuyoshi Nakada) about 12 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r37072.
Kenta, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
thread_pthread.c: init stack with ulimit
- thread_pthread.c (ruby_init_stack): use getrlimit() for the main
thread on Mac OS X, since pthread_get_stack{addr,size}_np() and
return the default value always, but not the ulimit value.
[ruby-dev:46174] [Bug #7084]
Updated by ko1 (Koichi Sasada) about 12 years ago
これって,r37072 で直ったんでしょうか.
Updated by mrkn (Kenta Murata) about 12 years ago
- Status changed from Closed to Open
まだ直ってません。ulimit -s 32768 の場合はきちんと SystemStackError で終了しましたが、
ulimit -s 4096 の場合に Segmentation Fault が発生しています。
さっき追加で調査した結果を以下に述べます。
https://gist.github.com/3828296
この gist に貼った 1.patch を当てて問題をコードを実行すると、
1.log として貼付けたように iseq_compile_each のローカル変数 type のアドレスがずらずら表示されます。
前後に隣り合うアドレスの差分を計算すると、再帰呼び出し1段で type のアドレスが6928も変化していてページサイズより大きいため、
ruby_stack_overflowed_p でスタックオーバーフローの判定に失敗しているのかなぁと推測しました。
そこで、iseq_compile_each の中の switch 文を複数の関数に分離して実行してみました。
https://gist.github.com/3828416
iseq_compile_each が使うスタックのサイズは560まで減りましたが、依然としてスタックオーバーフローの判定に失敗してます。
ここまでやって力尽きたので、また日を改めて調査します。
Updated by nobu (Nobuyoshi Nakada) about 12 years ago
- Status changed from Open to Closed
This issue was solved with changeset r37080.
Kenta, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
thread_pthread.c: precise stack size
- thread_pthread.c (ruby_init_stack): round stack limit to page size
boundary to calculate stack size more precisely. [ruby-dev:46174]
[Bug #7084]