Segfault on embedded ruby.

G

Godot

Hi,
This following problem is most likely due to my own
misunderstandings, but I've not been able to resolve it after staring
and scratching my head for quite a while. Here it is:

---------------Start code---------------

#include <ruby.h>
#include <iostream>
#include <string>
using namespace std;

void dontCrash(string s)
{
VALUE test = rb_str_new2( s.c_str( ) );
rb_gc_register_address(&test);
rb_gc( ); // Test if gc gets corrupted
rb_p( rb_str_new2(" stuff!!! ") );
rb_p( test );
rb_gc_unregister_address(&test);
}

int main ()
{
ruby_init ();
ruby_init_loadpath ();
dontCrash("puts 'test'");
ruby_finalize();
}

-------------- End code --------------------

The code (as reported by valgrind) always crashes on rb_gc( ).
Without the rb_gc( ), the code runs fine. It also crashes when
rb_register_address isn't called. This error has really got me
stumped, so any help is greatly appreciated.

Thanks,
-Godot
 
P

Paul Brannan

It doesn't crash for me.

What platform (os, ruby version, compiler, etc.) are you using?

Where in rb_gc() does the crash occur?

Does valgrind report anything out of the ordinary? (you'll probably want
to use a suppressions file such as the one in [ruby-talk:52065]).

Paul
 
G

Godot

It doesn't crash for me.
What platform (os, ruby version, compiler, etc.) are you using?

That's strange,
Im using gentoo linux, ruby version emerged is 1.8.0-r6, compiling command
is 'g++ testruby.cpp -g -lruby18 -I<ruby path>'
Ive checked the version of ruby by printing out the defines
RUBY_VERSION and RUBY_RELEASE_DATE, and the library/include matches up.

Ive just tried it with ruby 1.8.1-r6 and this dumps as well.

Hmm... This is stranger, it works with ruby 1.6.8. Has garbage collection
management methods changed in between versions?
Where in rb_gc() does the crash occur?

The following is from gdb, valgrind gives many errors, all related to
rb_gc and rb_gc_mark_locations, but it is very verbose:

Program received signal SIGSEGV, Segmentation fault.
0x4007c683 in rb_gc_mark_locations () from /usr/lib/libruby18.so.1.8
(gdb) bt
#0 0x4007c683 in rb_gc_mark_locations () from /usr/lib/libruby18.so.1.8
#1 0x4007e156 in rb_gc () from /usr/lib/libruby18.so.1.8
#2 0x08048b18 in dontCrash(std::string) (s=Cannot access memory at address 0x0
) at testruby.cpp:12
#3 0x08048b8f in main () at testruby.cpp:22


Thanks again,
-Godot
 
N

nobu.nokada

Hi,

At Mon, 7 Jun 2004 04:33:40 +0900,
Godot wrote in [ruby-talk:102597]:
---------------Start code---------------

#include <ruby.h>
#include <iostream>
#include <string>
using namespace std;
extern "C" void Init_stack(VALUE*);
void dontCrash(string s)
{
VALUE test = rb_str_new2( s.c_str( ) );
rb_gc_register_address(&test);
rb_gc( ); // Test if gc gets corrupted
rb_p( rb_str_new2(" stuff!!! ") );
rb_p( test );
rb_gc_unregister_address(&test);
}

int main ()
{
ruby_init ();
VALUE dummy;
Init_stack(&dummy);
 
P

Paul Brannan

VALUE dummy;
Init_stack(&dummy);

ruby_init() calls Init_stack, so why should this be necessary?

Any why does it matter anyway whether the stack is properly initialized
jn this case, since the address is being registered with the garbage
collector? (and thus the object should be marked just fine)

Paul
 
N

nobu.nokada

Hi,

At Tue, 8 Jun 2004 12:24:31 +0900,
Paul Brannan wrote in [ruby-talk:102734]:
ruby_init() calls Init_stack, so why should this be necessary?

To adjust the stack boundary.
The stack frame inside Init_stack() called from ruby_init()
would be placed at lower address than one of dontCrash() , so
that `test' in it would be outside the region of GC target.
 
G

Godot

Hi,

At Tue, 8 Jun 2004 12:24:31 +0900,
Paul Brannan wrote in [ruby-talk:102734]:
ruby_init() calls Init_stack, so why should this be necessary?

To adjust the stack boundary.
The stack frame inside Init_stack() called from ruby_init()
would be placed at lower address than one of dontCrash() , so
that `test' in it would be outside the region of GC target.

It works now :) Thanks for all the help, I don't think I would've
come across that solution on my own. I'm still struggling to understand
why 1.6.8-r10 didn't crash while 1.8* did, however.

-Godot
 
P

Paul Brannan

To adjust the stack boundary.
The stack frame inside Init_stack() called from ruby_init()
would be placed at lower address than one of dontCrash() , so
that `test' in it would be outside the region of GC target.

But test was marked with rb_gc_register_address(). Shouldn't that
function work with addresses that are not on the stack?

Paul
 
T

ts

P> But test was marked with rb_gc_register_address(). Shouldn't that
P> function work with addresses that are not on the stack?

this is when ruby mark the stack that it has a problem, but the example
was badly written for an embedded application because it call ruby
function without any protection (rb_protect(), etc)

bad, bad, bad


Guy Decoux
 
G

Godot

P> But test was marked with rb_gc_register_address(). Shouldn't that
P> function work with addresses that are not on the stack?

this is when ruby mark the stack that it has a problem, but the example
was badly written for an embedded application because it call ruby
function without any protection (rb_protect(), etc)

bad, bad, bad


Guy Decoux

Are you saying that I should rb_protect on rb_gc? Would that catch the
fault? That doesn't seem possible - but when it comes to ruby, Alot of
things that are seem impossible :)

This was only an example illustrating a problem I was having on a larger
application. It was by no means meant to be more than that, but I do
appreciate the warning.

-Godot
 
N

nobu.nokada

Hi,

At Tue, 8 Jun 2004 23:40:36 +0900,
Paul Brannan wrote in [ruby-talk:102783]:
But test was marked with rb_gc_register_address(). Shouldn't that
function work with addresses that are not on the stack?

I've understood that [ruby-talk:102597] doesn't crash when
rb_gc_register_address() is called, wrong?

At Mon, 7 Jun 2004 04:33:40 +0900,
Godot wrote in [ruby-talk:102597]:
 
T

ts

G> Are you saying that I should rb_protect on rb_gc? Would that catch the
G> fault? That doesn't seem possible - but when it comes to ruby, Alot of
G> things that are seem impossible :)

No, I was trying to say that your example was badly written. In an
embedded application, after the initialization phase you must *never* make
a call to a ruby function which is not protected with rb_protect(), or
what you want.

If ruby detect an error when it call a function, it will call longjmp()
and this can crash your application if you have not made a previous call
to rb_protect(), ...

If your application is well written, you don't need Init_stack()


Guy Decoux
 
P

Paul Brannan

I've understood that [ruby-talk:102597] doesn't crash when
rb_gc_register_address() is called, wrong?

Maybe I read it wrong, but I thought it crashed regardless of whether it
was called.

Paul
 
G

Godot

I've understood that [ruby-talk:102597] doesn't crash when
rb_gc_register_address() is called, wrong?

Maybe I read it wrong, but I thought it crashed regardless of whether it
was called.

Paul


That's correct, rb_gc_register_address doesn't prevent the crash, and the
more I read about Init_stack, the more I question why it even needs to be
called (although that does fix it).

This is from http://www.rubygarden.org/ruby?RubyApi/InitStack :

" If ruby_init() is not called from main(), you may need to use Init_stack
so Ruby knows the true bounds of the stack."

Now, either this wiki entry is only partially true, or ...?

Clueless as usual,
-Godot
 
N

nobu.nokada

Hi,

At Thu, 10 Jun 2004 04:13:41 +0900,
Godot wrote in [ruby-talk:102983]:
That's correct, rb_gc_register_address doesn't prevent the crash, and the
more I read about Init_stack, the more I question why it even needs to be
called (although that does fix it).

Hmmm, rb_gc_register_address should do. Something other might
go wrong.
This is from http://www.rubygarden.org/ruby?RubyApi/InitStack :

" If ruby_init() is not called from main(), you may need to use Init_stack
so Ruby knows the true bounds of the stack."

Now, either this wiki entry is only partially true, or ...?

It is difficult to say generally without assembler details,
because it is affected by compile option and so on.
 
T

ts

n> Hmmm, rb_gc_register_address should do. Something other might
n> go wrong.

yes, there is something else

n> It is difficult to say generally without assembler details,
n> because it is affected by compile option and so on.

you have found :)

Now the original poster just need to write correctly its program.


Guy Decoux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top