我希望程序在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'。 –