gdb ruby $pid

gdb is my “tool of last resort”. When all other online diagnostics have failed, I know enough gdb to pull out a C level stack trace.

  % gdb $SHELL $$
  GNU gdb 6.3.50-20050815 (Apple version gdb-477) (Sun Apr 30 20:06:22 GMT 2006)
  /Users/dom/320: No such file or directory.
  Attaching to program: `/bin/zsh', process 320.
  Reading symbols for shared libraries ........ done
  0x90006108 in syscall ()
  (gdb) where
  #0  0x90006108 in syscall ()
  #1  0x00054558 in signal_suspend ()
  #2  0x0002c9a8 in waitforpid ()
  #3  0x0002cb4c in waitjobs ()
  #4  0x00012584 in execlist ()
  #5  0x00011c24 in execlist ()
  #6  0x00011874 in execode ()
  #7  0x00026890 in loop ()
  #8  0x0002945c in zsh_main ()
  #9  0x00001d14 in start ()

It’s not terribly informative, but in the past, it’s given me just enough of a clue to start looking at the SSL libraries (for example).

Jamis Buck has gone one better—he’s pulled a ruby stacktrace from a running process. Which seems quite magical to me indeed. I also think that you can turn most of what he’s done into a gdb macro. I’ll have to have a look at some examples

In the past, I’ve resorted installing a signal handler “just in case” to pull out this sort of information. All of my Perl apps have this in their startup files.

  $SIG{ USR2 } = sub { Carp::cluck("Caught SIGUSR2 in $$") };

Which is all very well, if you know what you need in advance. Which is not usually the case.


Update: Ok, turning it into a gdb macro is dead easy. Save this lot into ~/ruby.gdb

  # A quick hack to show the environment for a Ruby process.

  define printenv
    set $index = 0
    while environ[$index]
      x/1s environ[$index]
      set $index = $index + 1

  document printenv
    Display the environment for the current process.

  define rb_where
    set $ary = (int)backtrace(-1)
    set $count = *($ary+8)
    set $index = 0
    while $index < $count
      x/1s *((int)rb_ary_entry($ary, $index)+12)
      set $index = $index + 1

  document rb_where
    Show the ruby stacktrace.

To use it do source ~/ruby.gdb from the gdb session, and then you get two new commands: printenv and rb_where.

Oh yes, I do know how super-trivial all this would be if only I had DTrace. Roll on Leopard.