FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

do not recommend safe_dump_to (fixes #98) · hktkdmp/stacktrace@66aba44 · GitHub

Commit 66aba44

Browse files
committed
do not recommend safe_dump_to (fixes boostorg#98)
1 parent e75d2ff commit 66aba44

2 files changed

Lines changed: 66 additions & 49 deletions

File tree

‎doc/stacktrace.qbk‎

Lines changed: 36 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -57,53 +57,6 @@ Code from above will output something like this:
5757
[note By default the Stacktrace library is very conservative in methods to decode stacktrace. If your output does not look as fancy as in example from above, see [link stacktrace.configuration_and_build section "Configuration and Build"] for allowing advanced features of the library. ]
5858

5959

60-
[endsect]
61-
62-
[section Handle terminates, aborts and Segmentation Faults]
63-
64-
Segmentation Faults and `std::terminate` calls sometimes happen in programs. Programmers usually wish to get as much information as possible on such incidents, so having a stacktrace will significantly improve debugging and fixing.
65-
66-
`std::terminate` calls `std::abort`, so we need to capture stack traces on Segmentation Faults and Abort signals.
67-
68-
[warning Writing a signal handler requires high attention! Only a few system calls allowed in signal handlers, so there's no cross platform way to print a stacktrace without a risk of deadlocking. The only way to deal with the problem - [*dump raw stacktrace into file/socket and parse it on program restart].]
69-
70-
[warning Not all the platforms provide means for even getting stacktrace in async signal safe way. No stack trace will be saved on such platforms. ]
71-
72-
Let's write a handler to safely dump stacktrace:
73-
74-
[getting_started_terminate_handlers]
75-
76-
Registering our handler:
77-
78-
[getting_started_setup_handlers]
79-
80-
At program start we check for a file with stacktrace and if it exist - we're writing it in human readable format:
81-
82-
[getting_started_on_program_restart]
83-
84-
Now we'll get the following output on `std::terminate` call after the program restarts:
85-
86-
```
87-
Previous run crashed:
88-
0# 0x00007F2EC0A6A8EF
89-
1# my_signal_handler(int) at ../example/terminate_handler.cpp:37
90-
2# 0x00007F2EBFD84CB0
91-
3# 0x00007F2EBFD84C37
92-
4# 0x00007F2EBFD88028
93-
5# 0x00007F2EC0395BBD
94-
6# 0x00007F2EC0393B96
95-
7# 0x00007F2EC0393BE1
96-
8# bar(int) at ../example/terminate_handler.cpp:18
97-
9# foo(int) at ../example/terminate_handler.cpp:22
98-
10# bar(int) at ../example/terminate_handler.cpp:14
99-
11# foo(int) at ../example/terminate_handler.cpp:22
100-
12# main at ../example/terminate_handler.cpp:84
101-
13# 0x00007F2EBFD6FF45
102-
14# 0x0000000000402209
103-
```
104-
105-
[note Function names from shared libraries may not be decoded due to address space layout randomization. Still better than nothing.]
106-
10760
[endsect]
10861

10962
[section Better asserts]
@@ -137,6 +90,42 @@ Backtrace:
13790

13891
Now we do know the steps that led to the assertion and can find the error without debugger.
13992

93+
[endsect]
94+
95+
[section Handle terminates]
96+
97+
`std::terminate` calls sometimes happen in programs. Programmers usually wish to get as much information as possible on such incidents, so having a stacktrace significantly improves debugging and fixing.
98+
99+
Here's how to write a terminate handler that dumps stacktrace:
100+
101+
[getting_started_terminate_handlers]
102+
103+
Here's how to register it:
104+
105+
[getting_started_setup_terminate_handlers]
106+
107+
Now we'll get the following output on `std::terminate` call:
108+
109+
```
110+
Previous run crashed:
111+
0# my_terminate_handler(int) at ../example/terminate_handler.cpp:37
112+
1# __cxxabiv1::__terminate(void (*)()) at ../../../../src/libstdc++-v3/libsupc++/eh_terminate.cc:48
113+
2# 0x00007F3CE65E5901 in /usr/lib/x86_64-linux-gnu/libstdc++.so.6
114+
3# bar(int) at ../example/terminate_handler.cpp:18
115+
4# foo(int) at ../example/terminate_handler.cpp:22
116+
5# bar(int) at ../example/terminate_handler.cpp:14
117+
6# foo(int) at ../example/terminate_handler.cpp:22
118+
7# main at ../example/terminate_handler.cpp:84
119+
8# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
120+
9# 0x0000000000402209
121+
```
122+
123+
[warning There's a temptation to write a signal handler that prints the stacktrace on `SIGSEGV` or abort. Unfortunately, there's no cross platform way to do that without a risk of deadlocking. Not all the platforms provide means for even getting stacktrace in async signal safe way.
124+
125+
Generic recommendation is to *avoid signal handlers, use* platform specific ways to store and decode *core files*.
126+
]
127+
128+
140129
[endsect]
141130

142131

‎example/terminate_handler.cpp‎

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,42 @@ BOOST_NOINLINE void foo(int i) {
2323

2424
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2525

26-
//[getting_started_terminate_handlers
26+
//[getting_started_signal_handlers
2727

2828
#include <signal.h> // ::signal, ::raise
2929
#include <boost/stacktrace.hpp>
3030

3131
void my_signal_handler(int signum) {
3232
::signal(signum, SIG_DFL);
33+
34+
// Outputs nothing or trash on majority of platforms
3335
boost::stacktrace::safe_dump_to("./backtrace.dump");
36+
3437
::raise(SIGABRT);
3538
}
3639
//]
3740

3841
void setup_handlers() {
39-
//[getting_started_setup_handlers
42+
//[getting_started_setup_signel_handlers
4043
::signal(SIGSEGV, &my_signal_handler);
4144
::signal(SIGABRT, &my_signal_handler);
4245
//]
4346
}
4447

48+
49+
//[getting_started_terminate_handlers
50+
#include <cstdlib> // std::abort
51+
#include <exception> // std::set_terminate
52+
#include <iostream> // std::cerr
53+
54+
#include <boost/stacktrace.hpp>
55+
56+
void my_terminate_handler() {
57+
std::cerr << boost::stacktrace::stacktrace();
58+
std::abort();
59+
}
60+
//]
61+
4562
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4663

4764
BOOST_CONSTEXPR_OR_CONST std::size_t shared_memory_size = 4096 * 8;
@@ -92,6 +109,15 @@ inline void copy_and_run(const char* exec_name, char param, bool not_null) {
92109
}
93110
}
94111

112+
int run_0(const char* /*argv*/[]) {
113+
//[getting_started_setup_terminate_handlers
114+
std::set_terminate(&my_terminate_handler);
115+
//]
116+
foo(5);
117+
return 1;
118+
}
119+
120+
95121
int run_1(const char* /*argv*/[]) {
96122
setup_handlers();
97123
foo(5);
@@ -300,6 +326,7 @@ int test_inplace() {
300326

301327
int main(int argc, const char* argv[]) {
302328
if (argc < 2) {
329+
copy_and_run(argv[0], '0', true);
303330
#ifndef BOOST_WINDOWS
304331
// We are copying files to make sure that stacktrace printing works independently from executable name
305332
copy_and_run(argv[0], '1', true);
@@ -314,6 +341,7 @@ int main(int argc, const char* argv[]) {
314341
}
315342

316343
switch (argv[1][0]) {
344+
case '0': return run_0(argv);
317345
case '1': return run_1(argv);
318346
case '2': return run_2(argv);
319347
case '3': return run_3(argv);

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL