From: Jurij Smakov Date: 2011-09-06T05:46:36+09:00 Subject: [ruby-core:39285] [Ruby 1.9 - Bug #5244] Continuation causes Bus Error on Debian sparc Issue #5244 has been updated by Jurij Smakov. I poked at it a bit. While I don't understand fully what's going on, it looks like it's using _setjmp/longjmp, and one thing in setjmp page caught my eye: "setjmp() saves the stack context/environment in env for later use by longjmp(3). The stack context will be invalidated if the function which called setjmp() returns." I think that such invalidation takes place here. Function rb_callcc (in cont.c) does the following: rb_callcc(VALUE self) { volatile int called; volatile VALUE val = cont_capture(&called); if (called) { return val; } else { return rb_yield(val); } } In cont_capture() the _setjmp is invoked via if (ruby_setjmp(cont->jmpbuf)) { volatile VALUE value; value = cont->value; if (cont->argc == -1) rb_exc_raise(value); cont->value = Qnil; *stat = 1; return value; } else { *stat = 0; return cont->self; } So, after invoking _setjmp, cont_capture returns which, according to the man page, should invalidate the saved stack context. Later, when something in the rb_yield(val) call chain tries to do the longjmp, we arrive at the location where _setjmp was originally called (in cont_capture) with a smashed stack, resulting in a SIGBUS. The fact that it works for other arches (and even on sparc, if I rebuild everything with -O0 instead of -O2) is somewhat surprising, but it might be that it just working "by accident" in most cases (i.e. the saved stack is preserved, even though it's not guaranteed). ---------------------------------------- Bug #5244: Continuation causes Bus Error on Debian sparc http://redmine.ruby-lang.org/issues/5244 Author: Lucas Nussbaum Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: 1.9.3 Hi, $ ./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -rcontinuation -e 'callcc { |c| c.call }' -e:1: [BUG] Bus Error ruby 1.9.3dev (2011-08-26) [sparc-linux] -- Control frame information ----------------------------------------------- c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :callcc c:0003 p:0009 s:0006 b:0006 l:000fcc d:001d74 EVAL -e:1 c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH c:0001 p:0000 s:0002 b:0002 l:000fcc d:000fcc TOP -- Ruby level backtrace information ---------------------------------------- -e:1:in `
' -e:1:in `callcc' -- C level backtrace information ------------------------------------------- Bus error gdb says: (gdb) run -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -rcontinuation -e 'callcc { |c| c.call }' Starting program: /home/lucas/ruby1.9.1-1.9.3~preview1+svn33077/miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -rcontinuation -e 'callcc { |c| c.call }' [Thread debugging using libthread_db enabled] [New Thread 0xf7fc7b70 (LWP 31418)] [Thread 0xf7fc7b70 (LWP 31418) exited] process 31417 is executing new program: /home/lucas/ruby1.9.1-1.9.3~preview1+svn33077/ruby1.9.1 [Thread debugging using libthread_db enabled] [New Thread 0xf79e5b70 (LWP 31419)] Program received signal SIGBUS, Bus error. 0xf7f4d304 in cont_capture (stat=Cannot access memory at address 0x49 ) at cont.c:439 439 if (ruby_setjmp(cont->jmpbuf)) { (gdb) print cont Cannot access memory at address 0xfffffff9 -- http://redmine.ruby-lang.org