Add shared library warmup

This commit is contained in:
Jeremy 2023-11-20 22:41:24 -06:00
parent 7c49e64ba6
commit a6a64b5671
No known key found for this signature in database
GPG Key ID: B4C8300FEC395042
3 changed files with 29 additions and 0 deletions

View File

@ -423,6 +423,10 @@ namespace cpptrace {
`safe_generate_raw_trace` will just produce an empty trace and if object information can't be resolved in a signal-safe `safe_generate_raw_trace` will just produce an empty trace and if object information can't be resolved in a signal-safe
way then `get_minimal_object_frame` will not populate fields beyond the `raw_address`. way then `get_minimal_object_frame` will not populate fields beyond the `raw_address`.
**Another big note:** Calls to shared objects can be lazy-loaded where the first call to the shared object invokes
non-signal-safe functions such as `malloc()`. To avoid this, call these routines in `main()` ahead of a signal handler
to "warm up" the library.
Because signal-safe tracing is an involved process, I have written up a comprehensive overview of Because signal-safe tracing is an involved process, I have written up a comprehensive overview of
what is involved at [signal-safe-tracing.md](signal-safe-tracing.md). what is involved at [signal-safe-tracing.md](signal-safe-tracing.md).

View File

@ -80,6 +80,12 @@ Currently the only back-end that can unwind safely is libunwind. Currently, the
information in a signal-safe manner is `_dl_find_object`, which doesn't exist on macos (or windows of course). If anyone information in a signal-safe manner is `_dl_find_object`, which doesn't exist on macos (or windows of course). If anyone
knows ways to do these safely on other platforms, I'd be much appreciative. knows ways to do these safely on other platforms, I'd be much appreciative.
# A pitfall to be aware of
Calls to functions in shared objects can be lazy-loaded where the first call to the shared object invokes
non-signal-safe functions such as `malloc()`. To avoid this, call these safe cpptrace routines in `main()` ahead of a
signal handler to "warm up" the library.
# Signal-Safe Tracing With `fork()` + `exec()` # Signal-Safe Tracing With `fork()` + `exec()`
Of the three strategies, `fork()` + `exec()`, is the most technically involved and the only way to resolve while the Of the three strategies, `fork()` + `exec()`, is the most technically involved and the only way to resolve while the
@ -96,6 +102,8 @@ The main program handles most of the complexity for tracing from signal handlers
- Resolving raw frame pointers to minimal object frames - Resolving raw frame pointers to minimal object frames
- Sending that info to the other process - Sending that info to the other process
Also note: A warmup for the library is done in main.
A basic implementation is as follows: A basic implementation is as follows:
```cpp ```cpp
@ -155,7 +163,16 @@ void handler(int signo, siginfo_t* info, void* context) {
_exit(1); _exit(1);
} }
void warmup_cpptrace() {
// This is done for any dynamic-loading shenanigans
cpptrace::frame_ptr buffer[10];
std::size_t count = cpptrace::safe_generate_raw_trace(buffer, 10);
cpptrace::minimal_object_frame frame;
cpptrace::get_minimal_object_frame(buffer[0], &frame);
}
int main() { int main() {
warmup_cpptrace();
// Setup signal handler // Setup signal handler
struct sigaction action = { 0 }; struct sigaction action = { 0 };
action.sa_flags = 0; action.sa_flags = 0;

View File

@ -65,9 +65,17 @@ void handler(int signo, siginfo_t* info, void* context) {
_exit(1); _exit(1);
} }
void warmup_cpptrace() {
cpptrace::frame_ptr buffer[10];
std::size_t count = cpptrace::safe_generate_raw_trace(buffer, 10);
cpptrace::minimal_object_frame frame;
cpptrace::get_minimal_object_frame(buffer[0], &frame);
}
int main() { int main() {
cpptrace::absorb_trace_exceptions(false); cpptrace::absorb_trace_exceptions(false);
cpptrace::register_terminate_handler(); cpptrace::register_terminate_handler();
warmup_cpptrace();
struct sigaction action = { 0 }; struct sigaction action = { 0 };
action.sa_flags = 0; action.sa_flags = 0;