我希望程序在malloc()
期间收到信号后,将堆栈内容写入文件。为此,我尝试使用backtrace()
和backtrace_symbols_fd()
函数,但后来发现它们不是异步信号安全的。我编写了下面的代码来测试,看起来该程序在大多数运行中都挂起了。malloc期间接收信号
#include <execinfo.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
typedef int bool;
#define true 1
#define false 0
static void signal_handler_child(int sig)
{
char error_msg_buffer[4096];
int fd = open("./backtrace_log.txt", O_RDWR | O_TRUNC | O_CREAT, 0777);
strcpy(error_msg_buffer, "entered signal_handler_child()");
write(fd, error_msg_buffer, strlen(error_msg_buffer));
void* buffer[1024];
const int size = backtrace(buffer, 1024);
if(size <= 0)
{
strcpy(error_msg_buffer, "unable to dump call stack trace: backtrace() returned bad size");
write(fd, error_msg_buffer, strlen(error_msg_buffer));
return ;
}
backtrace_symbols_fd(buffer, size, fd);
close(fd);
_exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
{
pid_t pid = fork();
if(pid == 0)
{
signal(SIGSEGV, signal_handler_child);
while(true)
{
void *pointer = malloc(1000000);
free(pointer);
}
}
else if(pid == -1)
{
printf("fork() error\n");
}
else
{
sleep(3);
if(kill(pid, SIGSEGV) == -1)
printf("kill() error\n");
wait(NULL);
}
}
那么,怎样才能安全地我写堆栈内容到在这样一种情况文件?一般情况下,backtrace()
可以使用malloc()
吗?
而且该名男子页说
backtrace_symbols_fd()不调用malloc(3),因此可以在使用的情况,其中 后者的功能可能会失败。
但是,什么是功能backtrace_symbols_fd()
点,如果backtrace()
实际上是malloc()
影响?
我是linux api的新手,所以任何帮助表示赞赏。
你的信号处理器有多远?你的输出文件是否被创建?你看到文件中的任何输出吗?我在[backtrace()'源代码](https://code.woboq.org/userspace/glibc/debug/backtrace.c.html)中没有看到任何会导致死锁的东西。你可以尝试添加一些东西来写从'backtrace()'返回的指针到文件中。您可以从命令行运行'pstack PID'来对付死锁进程,以查看它挂起的位置。另外,您可能希望在写入文件的每个字符串的末尾添加一个“\ n”字符。 –
'malloc'不会比其他任何东西更容易受到信号或干扰处理程序。为什么要专门测试它? –
@Peach:默认情况下,许多现代系统[将'ptrace'限制为父进程](https://www.kernel.org/doc/Documentation/security/Yama.txt)。如果可以的话,使用'sudo'。 –