gpt4 book ai didi

c - 在 malloc 期间接收信号

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:04:26 25 4
gpt4 key购买 nike

我希望程序在 malloc() 期间收到信号后将堆栈内容写入文件。为此,我尝试使用 backtrace()backtrace_symbols_fd() 函数,但后来发现它们不是异步信号安全的。我写了下面的代码只是为了测试,看起来程序在大多数运行中都挂了。

#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() does not call malloc(3), and so can be employed in situations where the latter function might fail.

但是,如果 backtrace() 实际上受到 malloc() 的影响,函数 backtrace_symbols_fd() 的意义何在?

我是 linux api 的新手,所以非常感谢任何帮助。

最佳答案

backtrace 调用malloc 的主要原因是它需要使用dlopen 加载libgcc_s。您可以通过首先调用 backtrace 来初始化自身来获得一些额外的可靠性。对 backtrace 的后续调用不应触发对 malloc 的调用,如以下示例所示。

#define _GNU_SOURCE
#include <dlfcn.h>
#include <execinfo.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void *
malloc (size_t size)
{
const char *message = "malloc called\n";
write (STDOUT_FILENO, message, strlen (message));
void *next = dlsym (RTLD_NEXT, "malloc");
return ((__typeof__ (malloc) *) next) (size);
}

int
main (void)
{
/* This calls malloc. */
puts ("First call to backtrace.");
void *buffer[10];
backtrace (buffer, 10);
/* This does not. */
puts ("Second call to backtrace.");
backtrace (buffer, 10);
}

由于其他原因,libgcc unwinder 仍然不是异步信号安全的,但 glibc 假设它是(对于线程取消之类的事情),并且它通常像异步信号安全一样工作。

关于c - 在 malloc 期间接收信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46863569/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com