Expand description
This module implements a crashtracker based on catching UNIX signals and uploading the result to the backend.
Architecturally, it consists of two parts:
- A signal handler, which catches a UNIX signal (SIGSEGV, SIGBUS, SIGABRT) associated with a crash, and and collects information about the state of the program at crash time. The signal handler runs under a constrained environment where many standard operations are illegal. https://man7.org/linux/man-pages/man7/signal-safety.7.html In particular, memory allocation, and synchronization such as mutexes, are potentially UB. The signal handler therefore does as little as possible in process, and instead writes data across a socket to a separate receiver process. The signal handler then waits for the receiver process to exit in order to reap its exit status (otherwise, upon the termination of the crashing process the child will be re-parented to PID 1 in the current PID namespace, which can be problematic for some user applications) and restores the previous signal handler. Once the receiver has completed, the crash-handler returns, allowing the previous crash handler (if any) to execute, maintaining the customer experience as much as possible.
- The receiver process, which is spawned by the signal handler. It is connected by an
anynomous AF_UNIX
socketpair()to the parent process. When a crash occurs, the receiver gathers the information from the pipe, adds additional data about the system state (e.g. /proc/cpuinfo and /proc/meminfo), formats it into a crash report, uploads it to the backend, and then exits. The signal handler must wait for the receiver in order to reap its exit status.
Data collected:
- The data collected by the crash-handler includes:
- The signal type leading to the crash
- The stacktrace at time of crash (for the crashing thread). Depending on a flag, this can either be resolved, or raw addresses. Resolving addresses provide more data, but sometimes crashes the crash handler (ironic).
- System level info (e.g. /proc/self/maps).
- The result of counters describing the current state of the profiler.
- Data augmented by the receiver includes:
- Metadata provided by the caller (e.g. library & profiler versions).
- System info: OS version, /proc/cpuinfo /proc/meminfo, etc.
- A timestamp and GUID for tracking the crash report.
Handling of forks Safety issues
Structs§
- Cached
ElfResolvers - Crash
Info - Crash
Info Builder - Crash
Ping - Crash
Ping Builder - Crashtracker
Configuration - Crashtracker
Configuration Builder - Crashtracker
Receiver Config - Error
Data - Error
Data Builder - Error
Object - Errors
Intake Config - Errors
Intake Payload - Errors
Intake Settings - Settings gathers configuration options we receive from the environment
- Errors
Intake Uploader - Experimental
- Metadata
- OsInfo
- Proc
Info - Runtime
Stack - Runtime stack representation for JSON serialization
- Runtime
Stack Frame - Shared
Library - SigInfo
- Span
- Stack
Frame - Stack
Trace - Telemetry
Crash Uploader - Thread
Data - Ucontext
- Structured representation of the CPU register state captured from a
ucontext_tat the time of a crash signal.
Enums§
- Build
IdType - Callback
Data - Callback
Error - Error
Kind - File
Type - OpTypes
- This enum represents operations a the tracked library might be engaged in. Currently only implemented for profiling. The idea is that if a crash consistently occurs while a particular operation is ongoing, its likely related.
- SiCodes
- See https://man7.org/linux/man-pages/man2/sigaction.2.html MUST REMAIN IN SYNC WITH THE ENUM IN emit_sigcodes.c
- Signal
Names - See https://man7.org/linux/man-pages/man7/signal.7.html
- Source
Type - Stacktrace
Collection - Stacktrace collection occurs in the context of a crashing process. If the stack is sufficiently corruputed, it is possible (but unlikely), for stack trace collection itself to crash. We recommend fully enabling stacktrace collection, but having an environment variable to allow downgrading the collector.
Constants§
Statics§
Traits§
Functions§
- async_
receiver_ entry_ point_ stream - async_
receiver_ entry_ point_ unix_ listener - async_
receiver_ entry_ point_ unix_ socket - begin_
op - Track that an operation (of type op) has begun. Currently, we assume states are discrete (i.e. not nested). PRECONDITIONS: This function assumes that the crash-tracker is initialized. ATOMICITY: This function is atomic.
- clear_
additional_ tags - clear_
runtime_ ⚠callback - Clear the registered runtime callback
- clear_
spans - clear_
traces - consume_
and_ emit_ additional_ tags - default_
max_ threads - default_
signals - disable
- Disables the crashtracker. Note that this does not restore the old signal handlers, but rather turns crash-tracking into a no-op, and then chains the old handlers. This means that handlers registered after the crashtracker will continue to work as expected.
- enable
- Enables the crashtracker, if had been previously disabled. If crashtracking has not been initialized, this function will have no effect.
- end_op
- Track that an operation (of type op) has finished. Currently, we assume states are discrete (i.e. not nested). PRECONDITIONS: This function assumes that the crash-tracker is initialized. ATOMICITY: This function is atomic.
- get_
expected_ receiver_ pid - Returns the currently registered expected receiver PID, or 0 if unset.
- get_
receiver_ unix_ socket - get_
registered_ ⚠callback_ type_ ptr - Get the callback type C string pointer from the currently registered callback
- get_
tests_ folder_ path - init
- Initialize the crash-tracking infrastructure.
- insert_
additional_ tag - insert_
span - insert_
trace - is_
runtime_ callback_ registered - Returns true if a callback is registered, false otherwise
- on_fork
- Reinitialize the crash-tracking infrastructure after a fork. This should be one of the first things done after a fork, to minimize the chance that a crash occurs between the fork, and this call. In particular, reset the counters that track the profiler state machine.
- receiver_
entry_ point_ stdin - receiver_
entry_ point_ unix_ socket - reconfigure
- Reconfigure the crash-tracking infrastructure.
- register_
runtime_ frame_ callback - register_
runtime_ stacktrace_ string_ callback - remove_
additional_ tag - remove_
span - remove_
trace - report_
unhandled_ exception - This function is designed to be when a program is at a terminal state and the application wants to report an unhandled exception to the crashtracker If this crashes, then the application will also crash. Ensure that this API is called when the application is at a terminal state and exit quickly after.
- reset_
counters - Resets all counters to 0. Expected to be used after a fork, to reset the counters on the child ATOMICITY: The reset of each individual counter is atomic, but the entire reset is NOT. Should only be used when no conflicting updates can occur, e.g. after a fork but before ops start on the child.
- set_
expected_ receiver_ pid - Register the expected receiver PID for socket-based crash receivers.
- signal_
from_ signum - Converts a signum into a Signal. Can’t use the from trait because we don’t own either type.
- translate_
si_ code - update_
config - Updates the crashtracker config for this process Config is stored in a global variable and sent to the crashtracking receiver when a crash occurs.
- update_
metadata - Updates the crashtracker metadata for this process Metadata is stored in a global variable and sent to the crashtracking receiver when a crash occurs.
Type Aliases§
- Runtime
Frame Callback - Function signature for runtime frame collection callbacks
- Runtime
Stacktrace String Callback - Function signature for runtime stacktrace string collection callbacks