Ruby C extension crash: how to create a stack trace?

B

barabba

Hi,

I am using ruby to test and develop my legacy C code. I packed it
inside a ruby extension as dll under windows. I am using visual
studio 6 to debug my extension.
The process works very well, but when I make a mistake in my C code
ruby abort without stack trace and it is difficult for me to find the
reason.
Here a trivial example. I have exported the buggy function
foo_thread_handler to ruby:

void foo_thread_handler()
{
while(1)
{
// a thread task
mystruct* pCrash = 0; // null pointer usage
pCrash->len = 555; // crash with 0xC0000005: Access
Violation.
do_realstuff(); // do real stuff
// call a function inside ruby to get back to the scheduler
rb_something()
}
}

and in ruby:
require 'myextension'
Thread.new {
begin
Myextension::foo_thread_handler()
rescue Exception => detail
puts " c extension code error"
end
}

def rb_something
puts "I am alive"
end

How can avoid ruby to silent abort when pCrash->len = 555; is
executed?
I am interested on stack trace, because it is not created, or an
assert to identify the code that make a crash.
Usually such exceptions are handled inside visual studio, but if I run
ruby inside it, in order to debug my extension, this doesn't happens.
I think to rebuild ruby and modify error.c to avoid abort() call
inside rb_bug(), but I am looking for a better solution.

Regards,
Igor
 
B

barabba

I have tried with :

trap("SEGV"){"my seg fault handler";exit}
Myextension::foo_thread_handler()

Trap seam to intercept the segmentation fault, but there is an
infinite recursion of the trap. The dos shell is blocked. If a run the
script inside visual studio, it is also blocked and I have to kill it
with task manager.
I use ruby under windows:
C:\Documents and Settings\igor>ruby -v
ruby 1.8.4 (2006-04-14) [i386-mswin32]
 
R

Ryan Davis

Hi,

I am using ruby to test and develop my legacy C code. I packed it
inside a ruby extension as dll under windows. I am using visual
studio 6 to debug my extension.
The process works very well, but when I make a mistake in my C code
ruby abort without stack trace and it is difficult for me to find the
reason.

I haven't done any MS development in over a decade (happily), so
maybe I'm just missing something. This is how I get a BT on OSX/
FreeBSD when I'm debugging my extensions:

% gdb ruby
r my_script.rb my_args .... go boom
bt
... backtrace with hopefully useful information

Can you not do that from the MS debugger???
 
B

barabba

I haven't done any MS development in over a decade (happily), so
maybe I'm just missing something. This is how I get a BT on OSX/
FreeBSD when I'm debugging my extensions:

% gdb ruby
.. backtrace with hopefully useful information

Can you not do that from the MS debugger???

Yes it is fast the same. MSVC start and run ruby using my_script.rb as
argument. The problem is the "backtrace", it is only one line, because
ruby don't crash, just exit.
I have solved my problem directly in the C part using Structured
Exception Handling(SEH) of win32.
Now my extension looks like:
void foo_thread_handler()
{
__try{
while(1)
{
// a thread task
mystruct* pCrash = 0; // null pointer usage
pCrash->len = 555; // BOOM
do_realstuff(); // do real stuff
// call a function inside ruby to get back to the scheduler
rb_something()
}
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
printf("Boom recognized\n");
}

}

This solution works only under MSVC compiler, but it is ok for me.

It is still not clear why
trap("SEGV"){"my seg fault handler";exit}
doesn't work on my system. It seam that the exception is caught, but
the C code is recalled at the same place where the error is generated
causing an infinite loop (may be an EXCEPTION_CONTINUE_EXECUTION is
used in the trap handler?).
 
P

Paul Brannan

Yes it is fast the same. MSVC start and run ruby using my_script.rb as
argument. The problem is the "backtrace", it is only one line, because
ruby don't crash, just exit.

Gdb stops when the application gets a signal, rather than waiting for
the application to terminate.
It is still not clear why
trap("SEGV"){"my seg fault handler";exit}
doesn't work on my system. It seam that the exception is caught, but
the C code is recalled at the same place where the error is generated
causing an infinite loop (may be an EXCEPTION_CONTINUE_EXECUTION is
used in the trap handler?).

If you segfault, you have already entered into the world of undefined
behavior. Anything your application does after that point is
unpredictable.

(For that reason, in most applications it's better to let the
application crash than to continue running in a bad state).

Do you get a stack trace if you place a breakpoint in sighandler() (in
signal.c)?

Paul
 
B

barabba

Gdb stops when the application gets a signal, rather than waiting for
the application to terminate.


If you segfault, you have already entered into the world of undefined
behavior. Anything your application does after that point is
unpredictable.

(For that reason, in most applications it's better to let the
application crash than to continue running in a bad state).

Do you get a stack trace if you place a breakpoint in sighandler() (in
signal.c)?

Paul

I have built a debug version of ruby 1.8.6 under windows with msvc6.
A breakpoint in sighandler() is not reached.
I have set also a breakpoint in sigsegv(sig)

This is the stack trace when the extension crash and reach the
breakpoint:
sigsegv(int 11) line 622
MSVCRT! 77c32efa()
RUBY! mainCRTStartup + 257 bytes
KERNEL32! 7c816d4f()

This say nothing where my extension crash, but maybe it is possible to
get more information using win32 GetExceptionInformation(). Not really
comfortable. May be it is better the possibility to turn off SEH
inside ruby and leave this to visual studio. But I haven't found in
ruby source how SEH are turned on.
 

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,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top