This repository was archived by the owner on Mar 9, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfatalsig.c
More file actions
110 lines (87 loc) · 2.29 KB
/
Copy pathfatalsig.c
File metadata and controls
110 lines (87 loc) · 2.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#define UNW_LOCAL_ONLY
#include <stdio.h>
#include <syslog.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <ucontext.h>
#include <libunwind.h>
#define FATALSIG_UNWIND_NAME_MAX_ 256
static void
fatalsig_action(int signo, siginfo_t *info, void *ctx)
{
struct sigaction sa;
unw_cursor_t cursor;
unw_context_t uc;
int ret = 0;
syslog(LOG_ERR, "program caught a fatal signal: %s (%d)",
strsignal(signo) != NULL ? strsignal(signo) : "Unknown",
signo);
unw_flush_cache(unw_local_addr_space, 0, 0);
if ((ret = unw_getcontext(&uc)) != 0) {
syslog(LOG_ERR,
"unable to get a stack unwind context: %s",
unw_strerror(ret));
goto propagate_signal;
}
if ((ret = unw_init_local(&cursor, &uc)) != 0) {
syslog(LOG_ERR,
"stack unwind initialization failed: %s",
unw_strerror(ret));
goto propagate_signal;
}
/* skip this function frame */
if ((ret = unw_step(&cursor)) < 0) {
syslog(LOG_ERR,
"failed to skip a signal handler stack frame: %s",
unw_strerror(ret));
}
if (ret <= 0) {
goto propagate_signal;
}
while ((ret = unw_step(&cursor)) > 0) {
char name[FATALSIG_UNWIND_NAME_MAX_];
unw_word_t ip, off;
unw_get_reg(&cursor, UNW_REG_IP, &ip);
ret = unw_get_proc_name(&cursor, name, sizeof(name), &off);
syslog(LOG_ERR,
" 0x%0*" PRIxPTR ": %s%s+0x%" PRIxPTR "\n",
(int) (2 * sizeof(void *)),
(uintptr_t) ip,
(ret == 0) ? name : "<unknown>",
(ret == 0) ? "()" : "",
(uintptr_t) off);
}
if (ret < 0) {
syslog(LOG_ERR, "stack unwind step failed: %s", unw_strerror(ret));
}
propagate_signal:
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sa.sa_flags = 0;
if (sigemptyset(&sa.sa_mask) != 0 ||
sigaction(signo, &sa, NULL) != 0 ||
kill(getpid(), signo) < 0)
{
syslog(LOG_ERR, "failed to propagate a signal");
}
}
int fatalsig_init(void)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = &fatalsig_action;
sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
if ((sigemptyset(&sa.sa_mask) != 0) ||
(sigaction(SIGSEGV, &sa, NULL) != 0) ||
(sigaction(SIGBUS, &sa, NULL) != 0) ||
(sigaction(SIGILL, &sa, NULL) != 0) ||
(sigaction(SIGABRT, &sa, NULL) != 0) ||
(sigaction(SIGFPE, &sa, NULL) != 0) ||
(sigaction(SIGSYS, &sa, NULL) != 0))
{
return -1;
}
return 0;
}