I'm trying to update a tool we've developed here at Rapleaf for  
observing what the threads in your app are up to (thread-dump). One  
of the limitations of thread-dump is that it can only produce the  
file, function and line for each thread, rather than the entire stack  
trace. It would be extremely handy in a lot of circumstances to know  
not just where the thread ended up but how it got there.

I have attempted to traverse each thread's frame list. It seems like  
this should be the ticket. However, I've found that in practice the  
process is ridiculously unstable when I try this approach. Almost  
immediately, I see bus errors or segmentation faults.

Is there some reason that it is impossible to traverse another  
thread's frames (and nodes, etc)? I've really been banging my head  
against this one. Admittedly, I'm not a C ninja, so I could use any  
pointers you've got. If there's an alternate approach that would make  
this easier, I'm all ears.

code (forgive the printf debugging statements):

static VALUE backtrace(rb_thread_t th)
{
   char buf[BUFSIZ];
   char buf2[BUFSIZ];
	char otherbuf[BUFSIZ];
   VALUE ary;
   NODE *n;
   struct FRAME *frame;

   n = th->node;
   frame = th->frame;
   ary = rb_ary_new();

   rb_ary_push(ary, rb_obj_id(th->thread));

   if (n) {
     snprintf(buf, BUFSIZ, "%s:%d", n->nd_file, nd_line(n));
		printf("Actual line: %s:%d\n", n->nd_file, nd_line(n));
     rb_ary_push(ary, rb_str_new2(buf));
   }

	while(frame->prev){
		if(frame->prev->last_func){
			if(strcmp(rb_id2name(frame->prev->last_func), "(null)") == 0){
				printf("func name was (null)\n");
			}
			else{
				printf("parent: %s\n", rb_id2name(frame->prev->last_func));
			}
		}
		else{
			printf("parent had no last func\n");
		}
	
		if(frame->prev->node){
			if(nd_line(frame->prev->node)){
				printf("parent line: %d\n", nd_line(frame->prev->node));
				if(frame->prev->node->nd_file){
					strcpy(frame->prev->node->nd_file, otherbuf);
					printf("parent file: %s\n", otherbuf);
					snprintf(buf2, BUFSIZ, "from %s:%d in %s", otherbuf, nd_line 
(frame->prev->node), rb_id2name(frame->prev->last_func));
					rb_ary_push(ary, rb_str_new2(buf2));
				}
			}
			else{
				printf("parent has no line\n");
			}
		}
		else{
			printf("parent has no node\n");
		}
		
		frame = frame->prev;
	}

   return ary;
}