[ruby-dev:50564] [Ruby trunk Bug#14387] Ruby 2.5 を Alpine Linux で実行すると比較的浅めで SystemStackError 例外になる
From:
s.wanabe@...
Date:
2018-06-10 10:49:45 UTC
List:
ruby-dev #50564
Issue #14387 has been updated by wanabe (_ wanabe).
naruse (Yui NARUSE) wrote:
> It's acceptable because it doesn't break other tested environment, but `getrlimit` really works on musl libc environment?
Thank you for your comment.
Okay, The patch needs one or more proofs of its behaviour, like that:
* Original issue [ruby-dev:50421] has gone away.
* Standard test codes run well.
* test-all
* ruby/spec
* `getrlimit` works on some situations like:
* on single thread
* with multiple threads
* with `RLIMIT_STACK` environment variable
* `getrlimit` code of musl is implemented correctly as expected.
* (But It's doubtful whether it can be. I guess that a proof of code soundness is very difficult.)
* Some "real world" applications can work.
* I think it is better example that that application(s) can't work without the patch.
I can't prove because I am not musl / Alpine guy.
Anyone can help?
----------------------------------------
Bug #14387: Ruby 2.5 を Alpine Linux で実行すると比較的浅めで SystemStackError 例外になる
https://bugs.ruby-lang.org/issues/14387#change-72459
* Author: koshigoe (Masataka SUZUKI)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v: ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux-musl]
* Backport: 2.3: DONTNEED, 2.4: DONTNEED, 2.5: REQUIRED
----------------------------------------
CircleCI で Alpine Linux を使って Ruby 2.5.0 で Rubocop を実行した時に遭遇した例外です(Ruby 2.4.3 では発生しませんでした)。
Ruby のバージョンによって、再帰が止められるまでの回数に大きな違いがあるのはなぜでしょうか?
これは、意図された挙動なのか、Ruby の変更によるものでは無く Alpine Linux 固有の問題なのか、教えていただく事は可能でしょうか?
Alpine Linux の Tread stack size が比較的小さい事で、Ruby 2.5.0 からこのような挙動になったのでしょうか?
https://wiki.musl-libc.org/functional-differences-from-glibc.html#Thread-stack-size
## 再現
問題の再現のため、以下の様な再帰するコードを実行します。
~~~ ruby
# test.rb
n = 100000
res = {}
1.upto(n).to_a.inject(res) do |r, i|
r[i] = {}
end
def f(x)
x.each_value { |v| f(v) }
end
f(res)
~~~
Ruby 2.4.3 で実行した場合、 10061 levels で例外があがりました。
~~~
% docker container run \
-v (pwd):/mnt/my --rm \
ruby:2.4.3-alpine3.7 \
ruby -v /mnt/my/test.rb
ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-linux-musl]
/mnt/my/test.rb:9:in `each_value': stack level too deep (SystemStackError)
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:9:in `block in f'
from /mnt/my/test.rb:9:in `each_value'
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:9:in `block in f'
from /mnt/my/test.rb:9:in `each_value'
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:9:in `block in f'
... 10061 levels...
from /mnt/my/test.rb:9:in `block in f'
from /mnt/my/test.rb:9:in `each_value'
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:12:in `<main>'
```
一方で Ruby 2.5.0 で実行した場合、 134 level で例外があがりました。
```
% docker container run \
-v (pwd):/mnt/my --rm \
test/ruby:trunk-alpine3.7 \
ruby -v /mnt/my/test.rb
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux-musl]
/mnt/my/test.rb:9:in `each_value': stack level too deep (SystemStackError)
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:9:in `block in f'
from /mnt/my/test.rb:9:in `each_value'
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:9:in `block in f'
from /mnt/my/test.rb:9:in `each_value'
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:9:in `block in f'
... 134 levels...
from /mnt/my/test.rb:9:in `block in f'
from /mnt/my/test.rb:9:in `each_value'
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:12:in `<main>'
```
また、Ruby trunk で実行した場合は 2.5.0 同等の結果になりました。
```
ruby 2.6.0dev (2018-01-24 trunk 62017) [x86_64-linux-musl]
/mnt/my/test.rb:9:in `each_value': stack level too deep (SystemStackError)
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:9:in `block in f'
from /mnt/my/test.rb:9:in `each_value'
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:9:in `block in f'
from /mnt/my/test.rb:9:in `each_value'
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:9:in `block in f'
... 134 levels...
from /mnt/my/test.rb:9:in `block in f'
from /mnt/my/test.rb:9:in `each_value'
from /mnt/my/test.rb:9:in `f'
from /mnt/my/test.rb:12:in `<main>'
```
※ trunk の Docker イメージを作った際の Dockerfile は以下。
https://gist.github.com/koshigoe/509be02a3580cdfc7a2cc45a4e6e44c5
---Files--------------------------------
0001-thread_pthread.c-make-get_main_stack-portable-on-lin.patch (2.61 KB)
--
https://bugs.ruby-lang.org/