신호 처리기로 오류를 catch 한 다음 스택 추적 정보를 인쇄하여 오류 보고서 및 디버깅을 위해 로그 파일 (또는 콘솔)에 추가하려고합니다. 비 개발 기계. 내 문제는 때로는 전체 스택 프레임 역 추적을 얻지 못한다는 것입니다. 매달리지 않고 끝내거나 끝내지 않는 경우가 많습니다. 때로는 성공적으로 종료됩니다.snprintf에서 strlen을 호출하는 중 backtrace_symbols_fd()를 호출하는 경우가 종종 발생합니다.
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <execinfo.h>
typedef struct { char name[10]; int id; char description[40]; } signal_def;
signal_def signal_data[] =
{
{ "SIGHUP", SIGHUP, "Hangup (POSIX)" },
{ "SIGINT", SIGINT, "Interrupt (ANSI)" },
{ "SIGQUIT", SIGQUIT, "Quit (POSIX)" },
{ "SIGILL", SIGILL, "Illegal instruction (ANSI)" },
{ "SIGTRAP", SIGTRAP, "Trace trap (POSIX)" },
{ "SIGABRT", SIGABRT, "Abort (ANSI)" },
{ "SIGIOT", SIGIOT, "IOT trap (4.2 BSD)" },
{ "SIGBUS", SIGBUS, "BUS error (4.2 BSD)" },
{ "SIGFPE", SIGFPE, "Floating-point exception (ANSI)" },
{ "SIGKILL", SIGKILL, "Kill, unblockable (POSIX)" },
{ "SIGUSR1", SIGUSR1, "User-defined signal 1 (POSIX)" },
{ "SIGSEGV", SIGSEGV, "Segmentation violation (ANSI)" },
{ "SIGUSR2", SIGUSR2, "User-defined signal 2 (POSIX)" },
{ "SIGPIPE", SIGPIPE, "Broken pipe (POSIX)" },
{ "SIGALRM", SIGALRM, "Alarm clock (POSIX)" },
{ "SIGTERM", SIGTERM, "Termination (ANSI)" },
//{ "SIGSTKFLT", SIGSTKFLT, "Stack fault" },
{ "SIGCHLD", SIGCHLD, "Child status has changed (POSIX)" },
//{ "SIGCLD", SIGCLD, "Same as SIGCHLD (System V)" },
{ "SIGCONT", SIGCONT, "Continue (POSIX)" },
{ "SIGSTOP", SIGSTOP, "Stop, unblockable (POSIX)" },
{ "SIGTSTP", SIGTSTP, "Keyboard stop (POSIX)" },
{ "SIGTTIN", SIGTTIN, "Background read from tty (POSIX)" },
{ "SIGTTOU", SIGTTOU, "Background write to tty (POSIX)" },
{ "SIGURG", SIGURG, "Urgent condition on socket (4.2 BSD)" },
{ "SIGXCPU", SIGXCPU, "CPU limit exceeded (4.2 BSD)" },
{ "SIGXFSZ", SIGXFSZ, "File size limit exceeded (4.2 BSD)" },
{ "SIGVTALRM", SIGVTALRM, "Virtual alarm clock (4.2 BSD)" },
{ "SIGPROF", SIGPROF, "Profiling alarm clock (4.2 BSD)" },
{ "SIGWINCH", SIGWINCH, "Window size change (4.3 BSD, Sun)" },
{ "SIGIO", SIGIO, "I/O now possible (4.2 BSD)" },
//{ "SIGPOLL", SIGPOLL, "Pollable event occurred (System V)" },
//{ "SIGPWR", SIGPWR, "Power failure restart (System V)" },
{ "SIGSYS", SIGSYS, "Bad system call" },
};
void bt_sighandler(int sig, siginfo_t *info, void *secret) {
signal_def *sigd = NULL;
for (int i = 0; i < sizeof(signal_data)/sizeof(signal_def); ++i) {
if (sig == signal_data[i].id) {
sigd = &signal_data[i];
break;
}
}
//ucontext_t* uc = (ucontext_t*) secret;
//void *pnt = (void*) uc->uc_mcontext.gregs[REG_RIP] ;
void *trace[16];
int trace_size = backtrace(trace, 16);
/* overwrite sigaction with caller's address */
//trace[1] = pnt;
if (sigd) {
fprintf(stderr, "SigHandler(0x%02X)[%d]:%s[%s]", sig, trace_size,
sigd->name, sigd->description);
} else {
fprintf(stderr, "SigHandler(0x%02X)[%d]", sig, trace_size);
}
backtrace_symbols_fd(trace, trace_size, fileno(stderr));
exit(1);
}
#endif
int main(int argc, char* argv[]) {
struct sigaction sa;
sa.sa_sigaction = bt_sighandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGBUS, &sa, NULL);
sigaction(SIGILL, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGUSR2, &sa, NULL);
signal(SIGPIPE, SIG_IGN);
//Produce a fault
return 0;
}
당신은 발신자의 주소를 가진은 sigaction을 덮어을 담당하는 부분은 주석 처리 된 내 샘플 코드에서 알 수 있습니다 :
여기 내 코드입니다. Mac 용으로 컴파일하는 방법을 모르기 때문입니다. 당신은 단지 처음 3 개 프레임을 인쇄 한 후 9 개 프레임이 발견 인쇄하기로했다 비록 종료하지 않고 걸린 것을 알 수 있습니다 console output http://www.minesclubtennis.com/images/stackoverflow/fatalconsoleoutputhang.png
: 여기
은 샘플 콘솔 출력됩니다.그래서 Activity Monitor 응용 프로그램에서 "샘플 프로세스"를 수행하여 backtrace_symbols_fd 기능을 실행하는 스레드가 strlen에 걸렸음을 발견했습니다. 스크린 샷 : sample process output http://www.minesclubtennis.com/images/stackoverflow/sampleprocessoutputhang.png
왜 걸려 있습니까? 이것은 내 코드의 버그입니까, 아니면 Apple backtrace의 버그입니까? 나는 신호 처리기로 할 수있는 제한된 것들이 있다고 들었지만, 나는 무엇이 잘못되었는지를 나타내는 sigaction man page에 아무것도 표시하지 않는다.
통찰력에 감사드립니다. 외관상으로는 다른 사람은이 기술을 사용하여 신호 처리기에서 백 트레이스를 생성 할 수 있다고 생각하기 때문에 일반적인 오해입니다. 내가 발견 한이 비디오 강연은 문제를 요약하고 해결책을 제시합니다. http://free-electrons.com/pub/video/2008/ols/ols2008-gilad-ben-yossef-fault-handlers.ogg 그의 강의에 설명 된 샘플 코드 프로젝트는 다음과 같습니다. https://github.com/gby/libcrash 샘플 코드와 plcrashreporter를 기반으로하는 자체 솔루션을 만들려고합니다. – BigMacAttack