Bug #7084

RubyVM::InstructionSequence.compile("1+"*10000 + "1") causes SystemStackError or Segmentation Fault

Added by Kenta Murata over 1 year ago. Updated over 1 year ago.

[ruby-dev:46174]
Status:Closed
Priority:Normal
Assignee:Koichi Sasada
Category:core
Target version:2.0.0
ruby -v:ruby 2.0.0dev (2012-09-29 trunk 37053) [x86_64-darwin12.1.0] Backport:

Description

以下のように ulimit -s の値に応じて stack level too deep と Segmentation Fault のどちらかが発生するようです。

$ .prefix/bin/ruby -v
ruby 2.0.0dev (2012-09-29 trunk 37053) [x8664-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:

Associated revisions

Revision 37072
Added by Nobuyoshi Nakada over 1 year ago

thread_pthread.c: init stack with ulimit

  • threadpthread.c (rubyinitstack): use getrlimit() for the main thread on Mac OS X, since pthreadgetstack{addr,size}np() and return the default value always, but not the ulimit value. [Bug #7084]

Revision 37080
Added by Nobuyoshi Nakada over 1 year ago

thread_pthread.c: precise stack size

  • threadpthread.c (rubyinit_stack): round stack limit to page size boundary to calculate stack size more precisely. [Bug #7084]

History

#1 Updated by Kenta Murata over 1 year ago

gdb で採取したバックとレースを gist に上げました。ulimit -s 8192 の場合です。参考までに。
https://gist.github.com/3803540

#2 Updated by Koichi Sasada over 1 year ago

(2012/09/29 18:27), mrkn (Kenta Murata) wrote:

以下のように ulimit -s の値に応じて stack level too deep と Segmentation Fault のどちらかが発生するようです。

 ええと,どうしたもんですかね.実装の都合でスタックオーバーフローするも
のは他にもありそうなので,これだけ頑張るべきか,よくわからないんですが....

 これだけ取り出した理由はなんでしょうか.こういう操作ってよくやるんです
かね.

--
// SASADA Koichi at atdot dot net

#3 Updated by Kenta Murata over 1 year ago

"1+"*10000 + "1" は YAPC::Asia の LT で見かけたネタです。

ulimit -s の値に依存して SEGV してしまう場合があるので、それだけでも直したいです。

#4 Updated by Koichi Sasada over 1 year ago

(2012/09/29 23:11), mrkn (Kenta Murata) wrote:

ulimit -s の値に依存して SEGV してしまう場合があるので、それだけでも直したいです。

 ulimit -s の値に依存せず SEGV するのはもっと嫌な気がしますが,それはと
もかく,直るのなら大変結構なことだと思います.よろしくお願いします.

--
// SASADA Koichi at atdot dot net

#5 Updated by Nobuyoshi Nakada over 1 year 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

  • threadpthread.c (rubyinitstack): use getrlimit() for the main thread on Mac OS X, since pthreadgetstack{addr,size}np() and return the default value always, but not the ulimit value. [Bug #7084]

#6 Updated by Koichi Sasada over 1 year ago

これって,r37072 で直ったんでしょうか.

#7 Updated by Kenta Murata over 1 year 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 として貼付けたように iseqcompileeach のローカル変数 type のアドレスがずらずら表示されます。

前後に隣り合うアドレスの差分を計算すると、再帰呼び出し1段で type のアドレスが6928も変化していてページサイズより大きいため、
rubystackoverflowed_p でスタックオーバーフローの判定に失敗しているのかなぁと推測しました。

そこで、iseqcompileeach の中の switch 文を複数の関数に分離して実行してみました。
https://gist.github.com/3828416

iseqcompileeach が使うスタックのサイズは560まで減りましたが、依然としてスタックオーバーフローの判定に失敗してます。

ここまでやって力尽きたので、また日を改めて調査します。

#8 Updated by Nobuyoshi Nakada over 1 year 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

  • threadpthread.c (rubyinit_stack): round stack limit to page size boundary to calculate stack size more precisely. [Bug #7084]

Also available in: Atom PDF