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

发布于 2024-08-02 10:19:31 字数 299 浏览 5 评论 0原文

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

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

我知道如何通过让监视线程执行 pstack (使用 system() 或通过分叉)来实现这一点。但我希望能够用C实现这个功能。有什么办法可以做到这一点吗?

我知道如何让线程通过遍历堆栈来打印其自己的调用堆栈,如果它命中断言,这很有用,但不知道如何为同一进程中的另一个线程执行此操作。

感谢您的任何帮助。 尼克B

In C on Solaris 10, I'd like to get the call stack from an arbitrary thread within a process.

I have many worker threads and one thread which monitors them all to detect tight loops and deadlocks. The function I'd like to implement is for the monitoring thread to print the call stack from the "hung" thread several times before it kills it.

I know how to implement this by having the monitoring thread execute pstack (with system() or by forking). But I would like to be able to implement this function in C. Is there any way to do this?

I know how to make a thread print its OWN call stack, by walking the stack, which is useful if it hits an assert, but not how to do this for another thread within the same process.

Thanks for any help.
NickB

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧夏天 2024-08-09 10:19:31

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

You can use walkcontext() to walk the stack, using dladdr()/dladdr1() to convert the addresses to function names. walkcontext() takes a ucontext for the thread. If you don't have the cooperation of that thread then you can obtain a ucontext for it by stopping the thread (e.g. with PCTWSTOP) and then reading its address from the pr_oldcontext field of the lwpstatus structure for that thread, obtained from /proc/self/lstatus.

萝莉病 2024-08-09 10:19:31

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

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

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

If you are using gcc you can use the inbuilt function __builtin_return_address.
void * __builtin_return_address (unsigned int level)

The function returns the address of the function from which the function is called. i.e the caller of the function.

The level specifies how many levels. 0 means current function 1 means caller, 2 means callers caller.
The following example will provide the usage. By printing the addresses of the function, the call stack can be determined.

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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文