File README.md changed (mode: 100644) (index 6cb613d..939a821) |
1 |
1 |
# Fault handling |
# Fault handling |
2 |
2 |
|
|
|
3 |
|
When the application crashes, e.g. due to derefencing `NULL`, a dump will be made. |
|
4 |
|
The dump will be shown on the Terminal and will saved in a log file called `/var/log/messages`. |
|
5 |
|
|
3 |
6 |
## Compiling |
## Compiling |
4 |
7 |
|
|
5 |
8 |
> Commands executed from repository's root. |
> Commands executed from repository's root. |
6 |
9 |
|
|
7 |
10 |
``` |
``` |
8 |
|
g++ main.cpp -o exe |
|
9 |
|
g++ main.cpp -g -o dbgexe |
|
|
11 |
|
g++ main.c -o exe |
|
12 |
|
g++ main.c -g -o dbgexe |
10 |
13 |
``` |
``` |
11 |
14 |
|
|
12 |
15 |
## Post mortem debugging |
## Post mortem debugging |
|
... |
... |
g++ main.cpp -g -o dbgexe |
14 |
17 |
Running `./exe` results in this output: |
Running `./exe` results in this output: |
15 |
18 |
|
|
16 |
19 |
``` |
``` |
17 |
|
Fout 11 at 0: |
|
18 |
|
Called from 4197438. |
|
19 |
|
Compiled at: May 22 2018 13:58:27 |
|
|
20 |
|
Error 11 at (nil): |
|
21 |
|
Called from 0x40233f |
|
22 |
|
Compiled at: May 30 2018 09:24:41 |
20 |
23 |
Aborted (geheugendump gemaakt) |
Aborted (geheugendump gemaakt) |
21 |
24 |
``` |
``` |
22 |
25 |
|
|
23 |
|
See what caused the error: |
|
|
26 |
|
In order to read the dump from the log file, while filtering all log info from other applications, one should execute the following command in a Terminal: |
|
27 |
|
|
|
28 |
|
``` |
|
29 |
|
# cat /var/log/messages | grep "postmortem-debugging" | sed 's/#012/\n\t/g' | less |
|
30 |
|
``` |
|
31 |
|
|
|
32 |
|
> Syslog turns newlines ('\n') in '#012'. The sed command reverts that. |
|
33 |
|
|
|
34 |
|
Possible output would be: |
|
35 |
|
|
|
36 |
|
``` |
|
37 |
|
May 30 09:38:14 localhost postmortem-debugging[14671]: Error 11 at (nil): |
|
38 |
|
May 30 09:38:14 localhost postmortem-debugging[14671]: Called from 0x40233f. |
|
39 |
|
May 30 09:38:14 localhost postmortem-debugging[14671]: Compiled at: May 30 2018 09:24:41 |
|
40 |
|
``` |
|
41 |
|
|
|
42 |
|
Let's see what caused the error by executing this one-liner: |
24 |
43 |
|
|
25 |
|
> Use the output from running ./exe ('Called from 4197438'). |
|
|
44 |
|
``` |
|
45 |
|
$ gdb ./dbgexe |
|
46 |
|
``` |
|
47 |
|
|
|
48 |
|
Then you need to use the information from the log file. Execute this code in `gdb`: |
26 |
49 |
|
|
27 |
50 |
``` |
``` |
28 |
|
gdb ./dbgexe |
|
29 |
|
l *4197438 |
|
|
51 |
|
l *0x40233f |
30 |
52 |
``` |
``` |
31 |
53 |
|
|
|
54 |
|
> Use the output from running ./exe ('Called from 0x40233f'). |
|
55 |
|
|
32 |
56 |
As `gdb` states, the error was caused at line 57: |
As `gdb` states, the error was caused at line 57: |
33 |
57 |
|
|
34 |
58 |
``` |
``` |
35 |
|
0x400c3e is in main() (main.cpp:57). |
|
|
59 |
|
0x40233f is in main() (main.cpp:71). |
36 |
60 |
``` |
``` |
File main.c renamed from main.cpp (similarity 53%) (mode: 100644) (index dca9011..833523d) |
1 |
|
#include <iostream> |
|
|
1 |
|
#ifndef _GNU_SOURCE |
|
2 |
|
#define _GNU_SOURCE |
|
3 |
|
#endif |
2 |
4 |
|
|
3 |
5 |
#include <unistd.h> |
#include <unistd.h> |
4 |
6 |
#include <signal.h> |
#include <signal.h> |
|
7 |
|
#include <syslog.h> |
|
8 |
|
|
|
9 |
|
#ifdef __cplusplus |
|
10 |
|
#include <iostream> |
|
11 |
|
#define ERR(X) std::cerr << X |
|
12 |
|
#define ABRT() std::abort() |
|
13 |
|
#else |
|
14 |
|
#include <ucontext.h> |
|
15 |
|
#include <stdio.h> |
|
16 |
|
#include <stdlib.h> |
|
17 |
|
#define ERR(X) perror(X) |
|
18 |
|
#define ABRT() abort() |
|
19 |
|
#endif |
5 |
20 |
|
|
6 |
21 |
void setHandler(void (*handler)(int,siginfo_t *,void *)) { |
void setHandler(void (*handler)(int,siginfo_t *,void *)) { |
7 |
22 |
struct sigaction action; |
struct sigaction action; |
|
... |
... |
void setHandler(void (*handler)(int,siginfo_t *,void *)) { |
9 |
24 |
action.sa_sigaction = handler; |
action.sa_sigaction = handler; |
10 |
25 |
|
|
11 |
26 |
if (sigaction(SIGFPE, &action, NULL) == -1) { |
if (sigaction(SIGFPE, &action, NULL) == -1) { |
12 |
|
std::cerr << "sigfpe: sigaction"; |
|
|
27 |
|
ERR("sigfpe: sigaction"); |
13 |
28 |
_exit(1); |
_exit(1); |
14 |
29 |
} |
} |
15 |
30 |
if (sigaction(SIGSEGV, &action, NULL) == -1) { |
if (sigaction(SIGSEGV, &action, NULL) == -1) { |
16 |
|
std::cerr << "sigsegv: sigaction"; |
|
|
31 |
|
ERR("sigsegv: sigaction"); |
17 |
32 |
_exit(1); |
_exit(1); |
18 |
33 |
} |
} |
19 |
34 |
if (sigaction(SIGILL, &action, NULL) == -1) { |
if (sigaction(SIGILL, &action, NULL) == -1) { |
20 |
|
std::cerr << "sigill: sigaction"; |
|
|
35 |
|
ERR("sigill: sigaction"); |
21 |
36 |
_exit(1); |
_exit(1); |
22 |
37 |
} |
} |
23 |
38 |
if (sigaction(SIGBUS, &action, NULL) == -1) { |
if (sigaction(SIGBUS, &action, NULL) == -1) { |
24 |
|
std::cerr << "sigbus: sigaction"; |
|
|
39 |
|
ERR("sigbus: sigaction"); |
25 |
40 |
_exit(1); |
_exit(1); |
26 |
41 |
} |
} |
27 |
42 |
} |
} |
|
... |
... |
void faultHandler(int signo, siginfo_t* info, void* extra) { |
37 |
52 |
#error Compiling for invalid architecture. |
#error Compiling for invalid architecture. |
38 |
53 |
#endif |
#endif |
39 |
54 |
|
|
40 |
|
std::cout << "Fout " << (int)signo << " at "; |
|
41 |
|
std::cout << (int&)info->si_addr << ": " << std::endl; |
|
42 |
|
std::cout << "Called from " << (int)i << "." << std::endl; |
|
43 |
|
std::cout << "Compiled at: " << __DATE__ << " " << __TIME__ << std::endl; |
|
|
55 |
|
openlog("postmortem-debugging", LOG_PERROR | LOG_PID, LOG_LOCAL0); |
|
56 |
|
|
|
57 |
|
syslog(LOG_ERR, "Error %d at %p:\n", signo, info->si_addr); |
|
58 |
|
syslog(LOG_ERR, "Called from %p.\n", i); |
|
59 |
|
syslog(LOG_ERR, "Compiled at: %s %s\n", __DATE__, __TIME__); |
|
60 |
|
|
|
61 |
|
closelog(); |
44 |
62 |
|
|
45 |
|
abort(); |
|
|
63 |
|
ABRT(); |
46 |
64 |
} |
} |
47 |
65 |
|
|
48 |
66 |
int main() { |
int main() { |
49 |
|
int* badptr = nullptr; |
|
|
67 |
|
int* badptr = NULL; |
50 |
68 |
|
|
51 |
69 |
setHandler(faultHandler); |
setHandler(faultHandler); |
52 |
70 |
|
|