Bug #5139

sigsegv のスタックオーバフロー

Added by Tomoyuki Chikanaga over 2 years ago. Updated over 2 years ago.

[ruby-dev:44315]
Status:Closed
Priority:Normal
Assignee:Motohiro KOSAKI
Category:core
Target version:1.9.4
ruby -v:- Backport:

Description

現在の trunk が Linux で testsegvtest(TestRubyOptions) が Failure になります。

$ ruby -e 'Process.kill :SEGV, $$'

のように実行すると表示されるはずのバックトレースや LOADED FEATURES の情報が表示されないためです。

おそらく r32751 からだと思うのですが、手元の環境(Ubuntu 10.4, Kernel 2.6.32-33-generic, gcc 4.4.3) では
どうやら sigsegv() から呼ばれている rbvmbugreport() で sigaltstack で設定したシグナルハンドラ用スタックを
オーバフローして、シグナルハンドラ内で再度 SEGV していると思います。

以下 gdb での実行の抜粋
(gdb) run -e 'Process.kill 11, $$'
Program received signal SIGSEGV, Segmentation fault.
0x0012d422 in _kernelvsyscall ()
(gdb) c
Continuing.
-e:1: [BUG] Segmentation fault
ruby 1.9.4dev (2011-08-01 trunk 32793) [i686-linux]
------------ snip -----------
* Loaded features:

Program received signal SIGSEGV, Segmentation fault.
0x08150864 in rbvmbugreport () at ../ruby/vmdump.c:834
834 for (i=0; i<RARRAY
LEN(vm->loadedfeatures); i++) {
(gdb) p ruby
currentthread->altstack
$5 = (void *) 0x8221ab8
(gdb) p $esp
$6 = (void *) 0x8220560
(gdb) p $esp - ruby
currentthread->altstack
$7 = -5464
(gdb) up
#1 0x08187095 in report
bug (file=0x82480b0 "-e", line=1,
fmt=0x81c3bcb "Segmentation fault", args=0x8222714 "\263\063")
at ../ruby/error.c:265
265 rbvmbugreport();
(gdb) p (char *)$esp - (char *)rubycurrentthread->altstack
$15 = -5144
(gdb) up
#2 0x08187121 in rbbug (fmt=0x81c3bcb "Segmentation fault")
at ../ruby/error.c:284
284 report
bug(file, line, fmt, args);
(gdb) p (char *)$esp - (char *)rubycurrentthread->altstack
$16 = 3112

$esp と rubycurrentthread->altstack の関係をみてオーバフローではないかと思ったのですがどうでしょう。
なお sigaltstack に渡しているスタックサイズは 4096 です。


Related issues

Related to ruby-trunk - Bug #7141: ALT_STACK_SIZE is not enough Closed 10/11/2012

Associated revisions

Revision 32815
Added by Yui NARUSE over 2 years ago

  • gc.c (init_heap): allocate sigaltstack after heaps are allocated.
    [Bug #5139]

  • vm.c (thread_free): use free because objspace is not ready.

  • vm.c (th_init): use malloc because objspace is not ready.

Revision 32844
Added by Motohiro KOSAKI over 2 years ago

  • error.c (report_bug): use a small message buffer instead of BUFSIZ. It is needed for avoiding nested SIGSEGV on Linux. Note: BUFSIZ is not proper buffer size. It's unrelated with maximum filename length. :-/ [Bug #5139]

History

#1 Updated by Nobuyoshi Nakada over 2 years ago

  • Status changed from Open to Assigned
  • Assignee set to Tomoyuki Chikanaga

こちらの環境(debian, 2.6.39-2-amd64, gcc-4.6.1)では再現しないのですが、gdbの結果を見る限りではそのようですね。

#2 Updated by Motohiro KOSAKI over 2 years ago

  • Assignee changed from Tomoyuki Chikanaga to Motohiro KOSAKI
  • Target version changed from 1.9.3 to 1.9.4

えっと、問題のコミットを入れたのはわたしなので、わたしが確認するべきと思います。
担当者を変更します。
また、問題のコミットは193ブランチには入れてないのでターゲットバージョンも変更します。
お手数をおかけして申し訳ありません。

#3 Updated by Tomoyuki Chikanaga over 2 years ago

すみませんターゲットバージョンは 1.9.3 にも入ったと勘違いしてました。

それから ALTSTACKSIZE を (SIGSTKSZ*2) (手元だと 16KB)に戻してやりなおしてみましたところ、
チケットの説明文に書いたような $esp のオーバフローはしていないのに vmbacktraceeach() で SEGV していたので
ちょっと別の問題が(も?)あるようです。

#4 Updated by Anonymous over 2 years ago

すみませんターゲットバージョンは 1.9.3 にも入ったと勘違いしてました。

それから ALTSTACKSIZE を (SIGSTKSZ*2) (手元だと 16KB)に戻してやりなおしてみましたところ、
チケットの説明文に書いたような $esp のオーバフローはしていないのに vmbacktraceeach() で SEGV していたので
ちょっと別の問題が(も?)あるようです。

中田さんの報告だとディストリ依存があるようなので、テストしたディストリとkernel, glibcのバージョンを
教えてもらえますでしょうか。
最近ちょっと忙しいので遅くなるかもしれませんが見てみます。

#5 Updated by Tomoyuki Chikanaga over 2 years ago

  • Target version changed from 1.9.4 to 1.9.3

試した環境は 2つあります。

A) Ubuntu 10.04.03
$ uname -srvm
Linux 2.6.32-33-generic #70-Ubuntu SMP Thu Jul 7 21:09:46 UTC 2011 i686
$ gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ /lib/libc.so.6 --version
GNU C Library (Ubuntu EGLIBC 2.11.1-0ubuntu7.8) stable release version 2.11.1, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.3.
Compiled on a Linux >>2.6.24-27-server<< system on 2011-01-21.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
For bug reporting instructions, please see:
http://www.debian.org/Bugs/.

B) Red Hat Enterprise Linux ES release 4 (Nahant Update 8)
$ uname -srvmp
Linux 2.6.9-89.ELlargesmp #1 SMP Mon Apr 20 10:43:12 EDT 2009 x8664 x8664
$ gcc-4.5 --version # configure --with-gcc で gcc-4.5 を指定
gcc-4.5 (GCC) 4.5.1
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ /lib/libc.so.6 --version
GNU C Library stable release version 2.3.4, by Roland McGrath et al.
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 3.4.6 20060404 (Red Hat 3.4.6-10).
Compiled on a Linux 2.4.20 system on 2009-01-09.
Available extensions:
GNU libio by Per Bothner
crypt add-on version 2.1 by Michael Glad and others
linuxthreads-0.10 by Xavier Leroy
The C stubs add-on version 2.1.2.
BIND-8.2.3-T5B
NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk
Glibc-2.0 compatibility add-on by Cristian Gafton
GNU Libidn by Simon Josefsson
libthread_db work sponsored by Alpha Processor Inc
Thread-local storage support included.
For bug reporting instructions, please see:
http://www.gnu.org/software/libc/bugs.html.

それぞれについて -O0 と -O3 でビルドしたもので -e 'Process.kill :SEGV, $$' を実行すると

(A)/-O0 => "[BUG]" まで表示して SEGV
(A)/-O3 => "[BUG]" まで表示して SEGV
(B)/-O0 => 再現せず(最後まで表示して abort で終了)
(B)/-O3 => "C level backtrace information" のバナーまで表示して SEGV

また (B) で ruby19_3 のブランチの HEAD を -O3 でビルドしてみたところ
(B)/-O3, 1.9.3 => "C level backtrace information" のバナーまで表示して SEGV
でした。
やはりスタックサイズだけが原因ではないみたいで 1.9.3 でも発生するのでバージョン 1.9.3 にしておきます。

手が空いたらもうちょっと条件を整理したいですが、とりあえず以上です。

#6 Updated by Yui NARUSE over 2 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r32815.
Tomoyuki, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


  • gc.c (init_heap): allocate sigaltstack after heaps are allocated.
    [Bug #5139]

  • vm.c (thread_free): use free because objspace is not ready.

  • vm.c (th_init): use malloc because objspace is not ready.

#7 Updated by Yui NARUSE over 2 years ago

  • Status changed from Closed to Assigned

#8 Updated by Yui NARUSE over 2 years ago

とりあえず r32815, r32821 にて boron では直ったんですが、chikanagaさんの環境ではどうですかね。
http://www.rubyist.net/~akr/chkbuild/debian/ruby-trunk/recent.html

#9 Updated by Akira Tanaka over 2 years ago

  • ruby -v changed from ruby 1.9.4dev (2011-08-01 trunk 32793) [i686-linux] to -

2011年8月3日9:00 Yui NARUSE naruse@airemix.jp:

とりあえず r32815, r32821 にて boron では直ったんですが、chikanagaさんの環境ではどうですかね。
http://www.rubyist.net/~akr/chkbuild/debian/ruby-trunk/recent.html

この issue 自体とは関係なくてなんですが、recent.html は内容がどんどん変わっていくページなので、
http://www.rubyist.net/~akr/chkbuild/debian/ruby-trunk/log/20110802T231900Z.diff.html.gz
みたいな、変化したところを直接参照しておいた方が、
もし将来調べる羽目になった時に面倒がないんではないかと思います。
--
[田中 哲][たなか あきら][Tanaka Akira]

#10 Updated by Tomoyuki Chikanaga over 2 years ago

(A) の 32bit マシンでは最新版の trunk で直っていました。
しかし (B) の x86_64 -O3 つきではやはり "C level backtrace information" まで表示して SEGV しています。

#11 Updated by Yui NARUSE over 2 years ago

Tomoyuki Chikanaga wrote:

(A) の 32bit マシンでは最新版の trunk で直っていました。
しかし (B) の x86_64 -O3 つきではやはり "C level backtrace information" まで表示して SEGV しています。

B) Red Hat Enterprise Linux ES release 4 (Nahant Update 8) って、r32751 より前ではきちんと動いてました?

#12 Updated by Tomoyuki Chikanaga over 2 years ago

(B) の -O3 では確かに r32749 でも、その前の r32748 でも同じエラーが出ていました。
すみません、(B) の -O3 はしばらく test-all を流していなかったので気がついてませんでしたが、
2011/05/01 の r31399 まで遡ってもまだ発生するので、この環境ではだいぶ前からこの問題があったみたいです。

#13 Updated by Motohiro KOSAKI over 2 years ago

  • Status changed from Assigned to Closed

RHEL4はもうplatform のほうがEOLなので深追いするだけ無駄だと思います。closeしましょう。

#14 Updated by Tomoyuki Chikanaga over 2 years ago

最新 trunk で RHEL4 で2度目の SEGV しているのは backtrace() の中とかなので glibc 古すぎとかかもしれません。

(gdb) where
#0 0x0000003feff07f2c in UnwindFindEnclosingFunction ()
from /lib64/libgccs.so.1
#1 0x0000003feff08e37 in _Unwind
Backtrace () from /lib64/libgccs.so.1
#2 0x0000003fed8db3df in backtrace () from /lib64/tls/libc.so.6
#3 0x0000000000531556 in rb
vmbugreport () at ../ruby/vmdump.c:40
#4 0x000000000057b866 in report_bug (file=Variable "file" is not available.
) at ../ruby/error.c:245
#5 0x0000203a313a652d in ?? ()
#6 0x0000000000000000 in ?? ()

ところで r32815 はメインスレッドの altstack を init_head() 後に確保しなおしているようですが、
なぜこれで直るのかというのがわかりません。もうしわけないのですが解説して頂けませんか。

#15 Updated by Yui NARUSE over 2 years ago

Tomoyuki Chikanaga wrote:

ところで r32815 はメインスレッドの altstack を init_head() 後に確保しなおしているようですが、
なぜこれで直るのかというのがわかりません。もうしわけないのですが解説して頂けませんか。

なんででしょうねぇ。
力尽くで探索して求めた位置なので、よくわからんです。

結局heapとaltstackの位置関係が変わっているのがキモだとは思うんですが。
なお、メインスレッドしかない場合thinitの方のaltstack確保は必要ないので、
むしろメインスレッドはinit
heap以降じゃないとダメだってのがこれの結論です。

#16 Updated by Tomoyuki Chikanaga over 2 years ago

結局heapとaltstackの位置関係が変わっているのがキモだとは思うんですが。
うーん、ということは altstack の位置が変わったためにスタックオーバフローしてもたまたま実害がなくなって現象が収まったということではないでしょうか。

なぜこんなにスタック使うのかというのを調べてみると、rbbug() から呼ばれる reportbug() で
char buf[BUFSIZ];
とバッファをスタック上に確保しているためのようでした。
ためしに
static char buf[BUFSIZ];
に変更して r32815r32821 を revert したバージョンでやってみても現象は収まりました。(buf を static に宣言していいかちゃんと考察していないので、とりあえず、ですが)

report_bug のスタック消費量を抑えるか、altstack のサイズを拡張するかするのがいいのではないかと思います。

#17 Updated by Tomoyuki Chikanaga over 2 years ago

  • Target version changed from 1.9.3 to 1.9.4

あと 1.9.3 で起きてたのは RHEL4 だけだったのでターゲットバージョンは再度 1.9.4 に戻します。お騒がせしてすみませんでした。

#18 Updated by Motohiro KOSAKI over 2 years ago

  • Status changed from Closed to Assigned

BUFSIZを使ってるのが根本的に間違っているという認識なので、もっと小さくしようと思います。メッセージサイズとなんの関係もない定数じゃないかっ。
ちなみにBUFSIZはMacでは1024, Linuxでは8096のようです。

#19 Updated by Motohiro KOSAKI over 2 years ago

  • Status changed from Assigned to Closed

This issue was solved with changeset r32844.
Tomoyuki, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


  • error.c (report_bug): use a small message buffer instead of BUFSIZ. It is needed for avoiding nested SIGSEGV on Linux. Note: BUFSIZ is not proper buffer size. It's unrelated with maximum filename length. :-/ [Bug #5139]

Also available in: Atom PDF