如何正确处理信号,让 gperftools CPU profiler 仍然有效?

Posted

技术标签:

【中文标题】如何正确处理信号,让 gperftools CPU profiler 仍然有效?【英文标题】:How to properly handle signals, so that gperftools CPU profiler still works? 【发布时间】:2013-10-25 05:52:45 【问题描述】:

我想分析我的守护程序,它会暂停主线程:

sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGTERM);
sigaddset(&signal_mask, SIGINT);

int sig;
sigwait(&signal_mask, &sig);

所有其他线程只是阻塞所有信号。 据我所知,分析器使用SIGPROF 信号进行操作。如果我开始使用这样的代码进行分析,则输出的 .prof 文件为空:

env CPUPROFILE=daemon.prof ./daemon

我应该如何正确处理主线程和其他线程中的信号以启用分析?或者可能是其他地方的问题?

【问题讨论】:

我正在“提高”你的问题,因为它提出了一个重要的问题 w.r.t.信号处理。 【参考方案1】:

所有其他线程只是阻塞所有信号。

您只需要在所有线程(或您要分析的线程)中取消阻止SIGPROF。我们只是在多线程守护进程中解决完全相同的问题。

【讨论】:

【参考方案2】:

我需要查看更多您的代码,但是您“所有其他线程只是阻塞所有信号”的声明引发了......信号。

您必须记住,大多数系统调用是在线程概念出现之前创建的。信号处理就是其中之一。因此,当您在任何线程上阻塞信号时,它很可能会被所有线程阻塞。

事实上,查看 signal(2) 手册页:

The effects of signal() in a multithreaded process are unspecified.

是的,这很可悲,但这是您必须为使用低开销的统计抽样分析器付出的代价。解决这个问题非常简单:只需从信号掩码集中删除 SIGPROF(或 SIGALRM,如果您使用的是 REAL 模式)就可以了。

一般来说,除非你绝对必须这样做,否则你不应该在主线程以外的任何地方进行进程级信号屏蔽......其中“main”不一定意味着 MAIN() 正在运行的线程在你认为是所有其他人的“老板”的线程中,原因你已经说得太清楚了。 :)

您也可以尝试使用pthread library's sigmask wrapper pthread_sigmask,,但我不清楚它在子线程从 sigmask 中删除条目(pthread 继承其父 pthread sigmask)等情况下的效果如何。

【讨论】:

至少在Linux中,有两种信号,进程范围的(发送到任何线程)和per-pthread(可以直接发送信号到特定线程)。仍然不知道,setitimer(发送 SIGPROF/SIGALRM)(my own question)使用了哪种信号。更新:主题groups.google.com/forum/#!topic/linux.kernel/DF-VwEf2AqE 说setitimer 使用了每线程信号。

以上是关于如何正确处理信号,让 gperftools CPU profiler 仍然有效?的主要内容,如果未能解决你的问题,请参考以下文章

我已经安装了 gperftools-2.0,但我无法获取 cpu 配置文件统计信息

让 gperftools 与 Rcpp 一起工作

使用带有排序的 gperftools 时分析计时器已过期

为golang程序使用pprof远程查看httpserver运行堆栈,cpu耗时等信息

硬件是如何发现与响应中断事件的?操作系统是如何处理中断的

从 C++ 中的 posix 信号处理程序获取对象属性