Getting a stack trace of a running thread

B

Bryan Duxbury

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;
}
 

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

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,229
Latest member
GloryAngul

Latest Threads

Top