从C中的任何线程获取调用堆栈

时间:2009-08-21 08:18:25

标签: c multithreading stack solaris call

在Solaris 10上的C中,我想从进程中的任意线程获取调用堆栈。

我有许多工作线程和一个线程,它们监视它们以检测紧密循环和死锁。我想要实现的功能是监视线程在“挂起”线程杀死之前多次从“挂起”线程打印调用堆栈。

我知道如何通过监视线程执行pstack(使用system()或forking)来实现这一点。但我希望能够在C中实现这个功能。有没有办法做到这一点?

我知道如何通过遍历堆栈来使线程打印其OWN调用堆栈,这在遇到断言时非常有用,但不知道如何在同一进程中为另一个线程执行此操作。

感谢您的帮助。 NickB

2 个答案:

答案 0 :(得分:4)

您可以使用walkcontext()遍历堆栈,使用dladdr()/dladdr1()将地址转换为函数名称。 walkcontext()为该主题获取ucontext。如果您没有该线程的合作,那么您可以通过停止线程(例如使用PCTWSTOP)然后从lwpstatus结构的pr_oldcontext字段读取其地址来获取它的ucontext该线程,从/proc/self/lstatus获得。

答案 1 :(得分:3)

如果您使用的是gcc,则可以使用内置函数__builtin_return_address。 void * __builtin_return_address(unsigned int level)

该函数返回调用函数的函数的地址。即函数的调用者。

级别指定了多少级别。 0表示当前功能1表示呼叫者,2表示呼叫者呼叫者。 以下示例将提供用法。通过打印函数的地址,可以确定调用堆栈。

int calla()
{
   printf("Inside calla\n");
   printf("A1=%x\n",__builtin_return_address (0));
   printf("A2=%x\n",__builtin_return_address (1) );
   printf("A3=%x\n",__builtin_return_address (2) );
}
int callb()
{
    printf("Inside callb\n");
    calle();
    printf("B1=%x\n",__builtin_return_address (0) );
    printf("B2=%x\n",__builtin_return_address (1) );
    printf("B3=%x\n",__builtin_return_address (2) );
}
int callc()
{
    printf("Inside callc\n");
    printf("C1=%x\n",__builtin_return_address (0) );
    printf("C2=%x\n",__builtin_return_address (1) );
    printf("C3=%x\n",__builtin_return_address (2) );
}
int calld()
{
    printf("Inside calld\n");
    printf("D1=%x\n",__builtin_return_address (0) );
    printf("D2=%x\n",__builtin_return_address (1) );
    printf("D3=%x\n",__builtin_return_address (2) );
}
int calle()
{
    printf("Inside calle\n");
    printf("E1=%x\n",__builtin_return_address (0) );
    printf("E2=%x\n",__builtin_return_address (1) );
    printf("E3=%x\n",__builtin_return_address (2) );
}
main()
{
    printf("Address of main=%x calla=%x callb=%x callc=%x calld=%x calle=%x\n",main,calla,callb,callc,calld,calle);
    calla();
    callb();
    calld();
}