Bug #10290
closedsegfault when calling a lambda recursively after rescuing SystemStackError
Description
The following code segfaults on Ruby 2.1.3:
l = -> { l.() }
begin
l.()
rescue SystemStackError
l.() # segfault
end
the issue does not occur on trunk.
Files
Updated by Anonymous about 10 years ago
The segfault also occurs on the OS X 10.9 system ruby, 2.0.0-p481
; not sure about the most recent patch release.
Updated by Anonymous about 10 years ago
I've attached the OS X crash report.
Updated by Anonymous about 10 years ago
As I noted, running the example code on trunk does not segfault (it raises SystemStackError a second time, as I would expect):
$ ruby -ve "l = -> { l.() }; begin; l.(); rescue SystemStackError; l.(); end"
ruby 2.2.0dev (2014-09-25 trunk 47651) [x86_64-darwin13]
-e:1:in `block in <main>': stack level too deep (SystemStackError)
from -e:1:in `call'
from -e:1:in `block in <main>'
from -e:1:in `call'
from -e:1:in `block in <main>'
from -e:1:in `call'
from -e:1:in `block in <main>'
from -e:1:in `call'
from -e:1:in `block in <main>'
... 9604 levels...
from -e:1:in `call'
from -e:1:in `block in <main>'
from -e:1:in `call'
from -e:1:in `<main>'
However, if I run the same code in IRB, it does segfault:
$ irb
irb(main):001:0> RUBY_DESCRIPTION
=> "ruby 2.2.0dev (2014-09-25 trunk 47651) [x86_64-darwin13]"
irb(main):002:0> l = -> { l.() }; begin; l.(); rescue SystemStackError; l.(); end
Segmentation fault: 11
I've attached the crash report for this one as well.
Updated by nobu (Nobuyoshi Nakada) about 10 years ago
I can't reproduce it with irb, but it might access over the top of stack.
Possibly, we need more margin for the guard page.
Updated by hsbt (Hiroshi SHIBATA) about 10 years ago
- Status changed from Open to Feedback
I can't reproduce following versions:
ruby 1.9.3p548 (2014-09-06) [x86_64-darwin13.4.0]
ruby 2.0.0p576 (2014-09-19 revision 47628) [x86_64-darwin13.4.0]
ruby 2.1.3p242 (2014-09-19 revision 47630) [x86_64-darwin13.0]
ruby 2.2.0preview1 (2014-09-17 trunk 47616) [x86_64-darwin13]
ruby 2.2.0dev (2014-10-13 trunk 47898) [x86_64-darwin13]
Updated by Anonymous about 10 years ago
I can reproduce it on 2.0.0-p576 when compiled with -Os
, but not -O2
:
$ make clean && ./configure --disable-install-doc CC=clang CFLAGS=-O2 && make -j12
$ ./miniruby -v
ruby 2.0.0p576 (2014-09-19 revision 47627) [x86_64-darwin13.4.0]
$ ./miniruby -e "l = -> { l.() }; begin; l.(); rescue SystemStackError; l.(); end"
-e:1: stack level too deep (SystemStackError)
$ make clean && ./configure --disable-install-doc CC=clang CFLAGS=-Os && make -j12
$ ./miniruby -v
ruby 2.0.0p576 (2014-09-19 revision 47627) [x86_64-darwin13.4.0]
$ ./miniruby -e "l = -> { l.() }; begin; l.(); rescue SystemStackError; l.(); end"
Segmentation fault: 11
On 2.1.3, it does not happen when compiled without optimizations, but even using -O1
is enough to trigger it:
$ make clean && ./configure --disable-install-doc CC=clang && make -j12
$ ./miniruby -v
ruby 2.1.3p242 (2014-09-19 revision 47629) [x86_64-darwin13.0]
$ ./miniruby -e "l = -> { l.() }; begin; l.(); rescue SystemStackError; l.(); end"
-e:1: stack level too deep (SystemStackError)
$ make clean && ./configure --disable-install-doc CC=clang CFLAGS=-O1 && make -j12
$ ./miniruby -v
ruby 2.1.3p242 (2014-09-19 revision 47629) [x86_64-darwin13.0]
$ ./miniruby -e "l = -> { l.() }; begin; l.(); rescue SystemStackError; l.(); end"
Segmentation fault: 11
And similarly on trunk, it is triggered with -O1
or higher:
$ make clean && ./configure --disable-install-doc CC=clang && make -j12
$ ./miniruby -v
ruby 2.2.0dev (2014-10-14 trunk 47906) [x86_64-darwin13]
$ ./miniruby -e "l = -> { l.() }; begin; l.(); rescue SystemStackError; l.(); end"
-e:1:in `call': stack level too deep (SystemStackError)
make clean && ./configure --disable-install-doc CC=clang CFLAGS=-O1 && make -j12
$ ./miniruby -v
ruby 2.2.0dev (2014-10-14 trunk 47906) [x86_64-darwin13]
$ ./miniruby -e "l = -> { l.() }; begin; l.(); rescue SystemStackError; l.(); end"
Segmentation fault: 11
I'm using the latest Apple clang:
$ clang --version
Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
Updated by hsbt (Hiroshi SHIBATA) about 10 years ago
I can't reproduce with gcc-4.9(not clang).
Updated by hsbt (Hiroshi SHIBATA) about 10 years ago
I can reproduce clang on linux.
[hsbt@chkbuild001 ~]$ clang -v
clang version 3.5.0 (tags/RELEASE_350/final)
Target: x86_64-amazon-linux-gnu
Thread model: posix
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-amazon-linux/4.8.2
Found candidate GCC installation: /usr/lib/gcc/x86_64-amazon-linux/4.8.2
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-amazon-linux/4.8.2
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
Updated by Anonymous about 10 years ago
I can reproduce it with gcc 4.9.1 at -Os
:
$ gcc-4.9 --version
gcc-4.9 (Homebrew gcc 4.9.1) 4.9.1
Copyright (C) 2014 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.
$ make clean && ./configure --disable-install-doc CC=gcc-4.9 CFLAGS=-Os && make -j12
$ ./miniruby -v
ruby 2.2.0dev (2014-10-16 trunk 47971) [x86_64-darwin13]
$ ./miniruby -e "l = -> { l.() }; begin; l.(); rescue SystemStackError; l.(); end"
Segmentation fault: 11
Updated by nobu (Nobuyoshi Nakada) about 10 years ago
- Description updated (diff)
I could reproduce it with gcc-4.9 on either Linux and OS X.
On Linux, SIGSEGV seems masked after the first stack overflow occurred, and it seems working by enabling interrupts.
diff --git c/eval.c i/eval.c
index 3e4ea16..6bd6ac9 100644
--- c/eval.c
+++ i/eval.c
@@ -500,7 +500,6 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause)
if (cause == Qundef) {
cause = nocause ? Qnil : get_thread_errinfo(th);
}
- exc_setup_cause(mesg, cause);
file = rb_sourcefile();
if (file) line = rb_sourceline();
@@ -526,6 +525,7 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause)
set_backtrace(mesg, at);
}
}
+ exc_setup_cause(mesg, cause);
if (!NIL_P(mesg)) {
th->errinfo = mesg;
diff --git c/signal.c i/signal.c
index d3c7cb8..b939930 100644
--- c/signal.c
+++ i/signal.c
@@ -767,6 +767,7 @@ check_stack_overflow(const uintptr_t addr, const ucontext_t *ctx)
* place. */
th->tag = th->tag->prev;
}
+ rb_enable_interrupt();
ruby_thread_stack_overflow(th);
}
}
However, on OS X it makes the second stack overflow SIGILL, with no outputs.
I have no idea what happens there.
Updated by backus (John Backus) over 8 years ago
Any update on this issue? I ran into this bug yesterday and spent hours investigating the source of the segfault. Here is the code that caused the issue for me:
def foo
define_singleton_method(:method_missing) { |*| invalid_method }
define_singleton_method(:define_singleton_method) { |*| invalid_method }
end
foo
begin
do_not_segfault
rescue SystemStackError
end
do_not_segfault
Updated by nobu (Nobuyoshi Nakada) over 8 years ago
It causes SystemStackError
as expected, with ruby 2.3.
Updated by backus (John Backus) about 8 years ago
Nobuyoshi Nakada wrote:
It causes
SystemStackError
as expected, with ruby 2.3.
No it definitely segfaults for me:
$ cat ex.rb
l = -> { l.() }
begin
l.()
rescue SystemStackError
l.() # segfault
end
$ which ruby
/Users/johnbackus/.rubies/ruby-2.3.1/bin/ruby
$ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
$ ruby ex.rb
[1] 82276 segmentation fault ruby ex.rb
anything I can run to help you reproduce for 2.3 on OS X?
Updated by shyouhei (Shyouhei Urabe) about 8 years ago
- Status changed from Feedback to Assigned
- Assignee set to nobu (Nobuyoshi Nakada)
ping nobu.
Updated by nobu (Nobuyoshi Nakada) over 7 years ago
On macOS, --with-setjmp-type=setjmp
configuration option may fix it.
Updated by backus (John Backus) over 7 years ago
nobu (Nobuyoshi Nakada) wrote:
On macOS,
--with-setjmp-type=setjmp
configuration option may fix it.
This does fix the issue on macOS for me, thank you. Maybe this should be the macOS default?
Updated by nobu (Nobuyoshi Nakada) over 7 years ago
SystemStackError
seems uncatchable since r58492.
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
- Status changed from Assigned to Closed
I was able to reproduce the segfault in ruby 2.3 and 2.4, but not in 2.5, 2.6, 2.7.0-preview1, or the master branch, so I think this problem is fixed. If this problem still occurs for you, please reply with your environment details.