juretta.com

Debugging Ruby -RubyOSA continued

January 08, 2007
Tags: Ruby RubyOSA

The day before yesterday i wrote a short post about RubyOSA. RubyOSA is a Ruby/AppleEvent Bridge which in the end means that you can use Ruby to script Mac OS X applications like iTunes, iChat, Address Book and many more.

As a small introductory example i wrote (read: quick, dirty hack) a small script to print all contacts in a Mac OS X Address Book.

Running this script with Ruby 1.8.4 worked just fine. Running it with Ruby 1.8.5 resulted in a (eval):2: [BUG] Segmentation fault ruby 1.8.5 (2006-12-25) [i686-darwin8.8.1]. Without further investigation i just wrote RubyOsa seems to work better with Ruby 1.8.4 than with Ruby 1.8.5.. What i should have done is what i like to explain in this post.

Laurent Sansonetti the maintainer and main developer of RubyOSA left a comment and asked about the problems with Ruby 1.8.5. The sensible thing to do in the first place would have been to investigate if Ruby 1.8.5 really caused the aforementionend segmentation fault and if that was the case - to file a bug report with as much information as needed.

Laurent asked me if Ruby had been build as a shared library. A quick and easy way to determine this is to check rbconfig.rb.

When building Ruby rbconfig.rb is being created with all relevant informations about the specific build. The following script prints all configuration options and shows if Ruby was built as a shared lib (mine actually was).

require 'rbconfig'

# Print all available configuration options
Config::CONFIG.each do |k,v|
  puts "#{k}: #{v}"
end                                        

# Ruby built as shared library?
puts Config::CONFIG['ENABLE_SHARED']  

To debug the Ruby interpreter or any low level library (like in this case) gdb the GNU Project debugger yields valuable informations.

GDB just recently gained a new momentum in the Rails community after Jamis Buck and Mauricio Fernandez described how to easily attach the gnu debugger to a running ruby process.

To debug a short running ruby script (without attaching the debugger to a process id) the following steps are neccessary:

Start gdb with the ruby interpreter as the first argument. You will get an interacive gdb session with a gdb prompt. There are more than 130 GDB commands but few will be sufficent to get the information that is needed.

macbook-sts:~/Desktop stefan$ gdb `which ruby`
GNU gdb 6.3.50-20050815 (Apple version gdb-573) 
[... output stripped...]
This GDB was configured as "i386-apple-darwin"...\
    Reading symbols for shared libraries .... done

Run the script that causes the bug. In this case it is rubyosa_ad.rb.

(gdb) run rubyosa_ad.rb
Starting program: /usr/local/bin/ruby rubyosa_ad.rb
Reading symbols for shared libraries .+... done
Reading symbols for shared libraries . done
Reading symbols for shared libraries . done
Reading symbols for shared libraries ... done
Reading symbols for shared libraries . done
Reading symbols for shared libraries ..............\
    ......................................... done
Reading symbols for shared libraries . done
Reading symbols for shared libraries . done
[... output stripped...]

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x6552534e
0x9000c5f8 in __vfprintf ()

The output now shows what is really happening: Program received signal EXC_BAD_ACCESS, Could not access memory.. To get even more information type backtrace (or bt) to get a backtrace.

(gdb) bt
#0  0x9000c5f8 in __vfprintf ()
#1  0x90022818 in snprintf ()
#2  0x000b4562 in rbosa_app_send_event (self=6878720, \
  event_class=6826060, event_id=6826040, params=6826020, \
  need_retval=2) at src/rbosa.c:231
#3  0x00217f54 in call_cfunc (func=0, recv=980578162, \
  len=-1, argc=0, argv=0x0) at eval.c:5672

GDB allows you to set breakpoints, step interactively through program execution and as shown in this really short example: Examine what has happened, when your program has stopped. This is what makes a bug report valuable and what really helps the developer who has to or wants to fix the bug you are reporting.

Laurent already fixed the bug in the RubyOSA trunk and even improved the address book example. The improved version is now in the RubyOSA sample directory which contains some interesting usage examples. Go and check them out!

For more information about GDB check out the GDB manual.

Have a look at RubyOSA or RubyCocoa - a Ruby/Objective-C Bridge for Mac OS X Cocoa. Great and interesting librarys for Ruby development on Mac OS X.


About

This is the defunct blog of Stefan Saasen.