Project

General

Profile

Bug #10290

segfault when calling a lambda recursively after rescuing SystemStackError

Added by jacknagel (Jack Nagel) over 4 years ago. Updated over 1 year ago.

Status:
Assigned
Priority:
Normal
Target version:
-
ruby -v:
ruby 2.1.3p242 (2014-09-19 revision 47629) [x86_64-darwin13.0]
[ruby-core:65254]

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

ruby_2014-09-25-000925_haswell.log (46.4 KB) ruby_2014-09-25-000925_haswell.log segfault on 2.1.3 jacknagel (Jack Nagel), 09/25/2014 05:10 AM
ruby_2014-09-25-001644_haswell.log (46.8 KB) ruby_2014-09-25-001644_haswell.log trunk segfault jacknagel (Jack Nagel), 09/25/2014 05:17 AM

History

Updated by jacknagel (Jack Nagel) over 4 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 jacknagel (Jack Nagel) over 4 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) over 4 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) over 4 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 jacknagel (Jack Nagel) over 4 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) over 4 years ago

I can't reproduce with gcc-4.9(not clang).

Updated by hsbt (Hiroshi SHIBATA) over 4 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 jacknagel (Jack Nagel) over 4 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) over 4 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 2 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 2 years ago

It causes SystemStackError as expected, with ruby 2.3.

Updated by backus (John Backus) over 2 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 2 years ago

  • Assignee set to nobu (Nobuyoshi Nakada)
  • Status changed from Feedback to Assigned

ping nobu.

Updated by nobu (Nobuyoshi Nakada) over 1 year ago

On macOS, --with-setjmp-type=setjmp configuration option may fix it.

Updated by backus (John Backus) over 1 year 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 1 year ago

SystemStackError seems uncatchable since r58492.

Also available in: Atom PDF