libexcept 1.1.19
Stack trace along C++ exceptions
Namespaces | Classes | Typedefs | Enumerations | Functions | Variables
libexcept Namespace Reference

Namespaces

namespace  anonymous_namespace{exception.cpp}
 
namespace  anonymous_namespace{report_signal.cpp}
 
namespace  anonymous_namespace{scoped_signal_mask.cpp}
 

Classes

class  exception_base_t
 
class  exception_t
 
class  logic_exception_t
 
class  out_of_range_t
 
class  scoped_signal_mask
 

Typedefs

typedef std::set< int > allowed_fds_t
 
typedef std::map< std::string, std::string > parameter_t
 
typedef std::list< int > sig_list_t
 
typedef std::list< std::string > stack_trace_t
 The stack trace results.
 

Enumerations

enum class  collect_stack_t {
  COLLECT_STACK_NO ,
  COLLECT_STACK_YES ,
  COLLECT_STACK_COMPLETE
}
 

Functions

static char const *LIBEXCEPT_VERSION_STRING __attribute__ ((unused))
 The library version as a string.
 
stack_trace_t collect_stack_trace (int stack_trace_depth)
 Collect the raw stack trace in a list of strings.
 
stack_trace_t collect_stack_trace_with_line_numbers (int stack_trace_depth)
 Collect the stack trace in a list of strings.
 
 DECLARE_LOGIC_ERROR (file_inherited)
 
 DECLARE_LOGIC_ERROR (fixme)
 
std::string demangle_cpp_name (char const *type_id_name)
 Demangle the specified type string.
 
collect_stack_t get_collect_stack ()
 Tells you whether the general flag is true or false.
 
std::string get_command_line (pid_t pid)
 Load the command line of the specified process.
 
int get_major_version ()
 Return the major version number.
 
int get_minor_version ()
 Return the minor version number.
 
int get_patch_version ()
 Return the patch version number.
 
char const * get_version_string ()
 Return a string to the version of the library when it was compiled.
 
bool has_sanitizer ()
 Check whether this instance is running with the sanitizer.
 
void init_report_signal ()
 Setup the callbacks.
 
void set_collect_stack (collect_stack_t collect_stack)
 Set a general flag on whether to collect stack traces or not.
 
void verify_inherited_files (allowed_fds_t allowed)
 Check the list of files opened in this process.
 

Variables

constexpr int const LIBEXCEPT_VERSION_MAJOR = 1
 
constexpr int const LIBEXCEPT_VERSION_MINOR = 1
 
constexpr int const LIBEXCEPT_VERSION_PATCH = 19
 
constexpr int const STACK_TRACE_DEPTH = 20
 Default depth of stack traces collected.
 

Typedef Documentation

◆ allowed_fds_t

typedef std::set<int> libexcept::allowed_fds_t

Definition at line 47 of file file_inheritance.h.

◆ parameter_t

typedef std::map<std::string, std::string> libexcept::parameter_t

Definition at line 57 of file exception.h.

◆ sig_list_t

typedef std::list<int> libexcept::sig_list_t

Definition at line 49 of file scoped_signal_mask.h.

◆ stack_trace_t

typedef std::vector< std::string > libexcept::exception_base_t::stack_trace_t

This typedef defines the type of the variables used to pass the stack trace between functions. It is a simple vector a C++ strings.

The first string (trace[0]) represents the current function. Note that the collected functions will include all the functions, including the exception_base_t::collect_stack_trace() and various calling functions from the libexcept library. In most cases this means 2 or 3 lines at the start of the stack trace vector are going to be about libexcept functions and not the function where the exception was raised.

Definition at line 41 of file stack_trace.h.

Enumeration Type Documentation

◆ collect_stack_t

enum class libexcept::collect_stack_t
strong
Enumerator
COLLECT_STACK_NO 
COLLECT_STACK_YES 
COLLECT_STACK_COMPLETE 

Definition at line 49 of file exception.h.

Function Documentation

◆ __attribute__()

static char const *LIBEXCEPT_VERSION_STRING libexcept::__attribute__ ( (unused)  )
static

This variable represents the full library version at the time you compile your program.

Warning
This variable uses an attribute supported by the GNU C++ compiler which prevents Doxygen from finding this help block if declared in the .cpp file. This is why it is in the header.
See also
version()

◆ collect_stack_trace()

stack_trace_t libexcept::collect_stack_trace ( int  stack_trace_depth)

This function collects the current stack as a trace to log later.

By default, the stack trace shows you a number of lines equal to STACK_TRACE_DEPTH (which is 20 at time of writing). You may specify another number to get more or less lines. Note that a really large number will generally show you the entire stack since a number larger than the number of function pointers on the stack will return the entire stack.

If you pass 0 as stack_trace_depth then the function returns an empty list of strings.

The stack_trace_depth parameter is silently clamped to 1,000, which in most cases will be more than enough to get the entire stack trace available.

Note
This function is global so we can use it anywhere we'd like to get a stack trace and not just in exceptions. Very practical in C++ to get a stack trace directly in a list of strings.
Attention
Use the collect_stack_with_line_numbers() to get demangled function names and line numbers. Note that this other function is considered very slow so do not use it in a standard exception. Consider using that other function only when debugging.
Parameters
[in]stack_trace_depthThe number of lines to capture in our stack trace.
Returns
The vector of strings with the stack trace.
See also
collect_stack_trace_with_line_numbers()
set_collect_stack()

Definition at line 100 of file stack_trace.cpp.

Referenced by libexcept::exception_base_t::exception_base_t(), and libexcept::anonymous_namespace{report_signal.cpp}::report_signal().

◆ collect_stack_trace_with_line_numbers()

stack_trace_t libexcept::collect_stack_trace_with_line_numbers ( int  stack_trace_depth)

This function collects the current stack as a trace including the line numbers and demangled function names as available.

The function also works like the collect_stack_trace() function.

Note
The function makes use of the addr2line and c++filt command line tools to convert the information. It is likely that if it fails it means your system does not have those two tools installed. Also, the addr2line requires the debug information in the libraries and executables. Without that information, you will still get invalid answers in your stacktrace.

See also the libbacktrace library: https://gcc.gnu.org/viewcvs/gcc/trunk/libbacktrace/

Parameters
[in]stack_trace_depthThe number of lines to capture in our stack trace.
Returns
The vector of strings with the stack trace.
See also
collect_stack_trace()
set_collect_stack()

Definition at line 149 of file stack_trace.cpp.

References demangle_cpp_name().

Referenced by libexcept::exception_base_t::exception_base_t().

◆ DECLARE_LOGIC_ERROR() [1/2]

libexcept::DECLARE_LOGIC_ERROR ( file_inherited  )

◆ DECLARE_LOGIC_ERROR() [2/2]

libexcept::DECLARE_LOGIC_ERROR ( fixme  )

◆ demangle_cpp_name()

std::string libexcept::demangle_cpp_name ( char const *  type_id_name)

C++ offers a typeid(\<type>).name() function, only that does not return a readable name in many cases. This function transforms that name back to the original. This is particularly useful for C++ base types. For example "unsigned short" becomes "t". To verify a type, it is quite practical.

This function demangles all names, including those we get when building a stack trace.

Note
This is similar to using the c++filt command line tool. If the conversion fails, then the function returns the input string as is.
I found a piece of code snippet on Catch2 which is used to demangle a C++ name. It is one simple ABI call!
#include "catch.hpp"
#include <cxxabi.h>
#include <typeinfo>
CATCH_TRANSLATE_EXCEPTION(std::exception& e) {
std::string s;
int status;
const char* name = typeid(e).name();
char* realname = abi::__cxa_demangle(name, 0, 0, &status);
if(realname) {
s.append(realname);
} else {
s.append(name);
}
s.append(": ");
s.append(e.what());
free(realname);
return s;
}

Source: https://github.com/catchorg/Catch2/issues/539

Parameters
[in]type_id_nameThe mangled C++ name.
Returns
The converted name.
See also
https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html

Definition at line 95 of file demangle.cpp.

Referenced by collect_stack_trace_with_line_numbers().

◆ get_collect_stack()

collect_stack_t libexcept::get_collect_stack ( )

This function gives you the current status of the collect stack flag. If true, when exceptions will collect the stack at the time they are emitted. This is very practical in debug since it gives you additional information of where and possibly why an exception occurred.

Definition at line 193 of file exception.cpp.

Referenced by libexcept::exception_base_t::exception_base_t().

◆ get_command_line()

std::string libexcept::get_command_line ( pid_t  pid)

This function loads the cmdline file of the specified process. If an error occurs, the function returns an empty string. Some processes do not have a command line.

If your program can include cppprocess (see eventdispatcher,) then I suggest you use the cppprocess::process_info class instead. It is much more powerful.

Parameters
[in]pidThe process identifier.
Returns
The command line of the pid process.

Definition at line 68 of file file_inheritance.cpp.

Referenced by verify_inherited_files().

◆ get_major_version()

int libexcept::get_major_version ( )

This function returns the library major version number when it was compiled as an integer. It can be used to compare against a version you support.

Returns
The library major version number when it was compiled.

Definition at line 51 of file version.cpp.

References LIBEXCEPT_VERSION_MAJOR.

◆ get_minor_version()

int libexcept::get_minor_version ( )

This function returns the library minor version number when it was compiled as an integer. It can be used to compare against a version you support.

Returns
The library minor version number when it was compiled.

Definition at line 63 of file version.cpp.

References LIBEXCEPT_VERSION_MINOR.

◆ get_patch_version()

int libexcept::get_patch_version ( )

This function returns the library patch version number when it was compiled as an integer. It can be used to compare against a version you support.

Returns
The library minor version number when it was compiled.

Definition at line 75 of file version.cpp.

References LIBEXCEPT_VERSION_PATCH.

◆ get_version_string()

char const * libexcept::get_version_string ( )

This function returns the library version when it was compiled as a string. It can be used to compare against a version you support (i.e. the version your software was compiled against could be different.)

Returns
A constant string that represents the library version.

Definition at line 39 of file version.cpp.

◆ has_sanitizer()

bool libexcept::has_sanitizer ( )
inline

This funciton returns true if the software was compiled with the sanitizer. This test happens at runtime. The test results are saved in global variables. To make it thread safe, it should be called once before starting any thread.

Note that by default the sanitizer is enabled, but it is possible to disable it using the __lsan_disable() function. There is no function I've seen that will tell you whether the sanitizer is currently enabled or disabled.

Returns
true if the running process has the sanitizer linked in.

Definition at line 169 of file scoped_signal_mask.cpp.

Referenced by libexcept::scoped_signal_mask::scoped_signal_mask().

◆ init_report_signal()

void libexcept::init_report_signal ( )

This function sets up the callbacks of all the signals representing a crash. The callback will print the stack to stderr.

If you are a project over eventdispatcher, you have several options at your disposal which are much better than this simplistic function:

  • signal – a connection that can catch any signal using the signalfd() function (i.e. the eventdispatcher can poll on it)
  • signal_handler – similar to this function, it capture signals and reports them in the logger including a stack trace
  • signal_child – an extension of the signal connection which provides additional data about the child that died
Warning
This code is not thread safe.

Definition at line 114 of file report_signal.cpp.

◆ set_collect_stack()

void libexcept::set_collect_stack ( collect_stack_t  collect_stack)

Because collecting the stack trace can be time consuming and once in a while you may need the highest possible speed including libexcept exceptions, we offer a flag to avoid all stack collection processing.

We especially use this feature when running tests because we generate the exceptions on purpose and do not want to get the stack trace which is rather useless in this case. We do not yet have any other situations where we do not want a stack trace.

By default collect_stack is already true so you do not need to change it on startup.

Warning
The function itself is not multithread safe. It is unlikely to cause any serious problems, though. Some threads may have or may be missing the stack trace, that's all. If you never call this function, all threads will always include the stack trace. Calling this function before you create threads will resolve all possible issues (if you do not have to dynamically change the flag.)
Parameters
[in]collect_stackWhether to collect the stack or not.

Definition at line 223 of file exception.cpp.

◆ verify_inherited_files()

void libexcept::verify_inherited_files ( allowed_fds_t  allowed)

This function reads the /proc/<pid>/fd directory. If it finds files other than 0, 1, 2, then it generates an error.

In Debug mode, the error is fatal (it throws).

In Release mode, the error is just a warning so the process still starts but you still get a message letting you know there may be something fishy going on.

In case your application actually accepts additional streams, you can add them to the allowed set of file descriptors.

Parameters
[in]allowedAdditional allowed input streams.

Definition at line 96 of file file_inheritance.cpp.

References get_command_line().

Referenced by main().

Variable Documentation

◆ LIBEXCEPT_VERSION_MAJOR

constexpr int const libexcept::LIBEXCEPT_VERSION_MAJOR = 1
constexpr

Definition at line 29 of file version.h.

Referenced by get_major_version().

◆ LIBEXCEPT_VERSION_MINOR

constexpr int const libexcept::LIBEXCEPT_VERSION_MINOR = 1
constexpr

Definition at line 30 of file version.h.

Referenced by get_minor_version().

◆ LIBEXCEPT_VERSION_PATCH

constexpr int const libexcept::LIBEXCEPT_VERSION_PATCH = 19
constexpr

Definition at line 31 of file version.h.

Referenced by get_patch_version().

◆ STACK_TRACE_DEPTH

int libexcept::exception_base_t::STACK_TRACE_DEPTH = 20
constexpr

This parameter defines the default number of lines returned by the collect_stack_trace() function.

All the functions that call the collect_stack_trace() have a stack_trace_depth parameter you can use to change this value.

Note that a value of 0 is valid as the stack trace depth. This just means not even one line is going to be taken from the stack.

Attention
It is to be noted that since a few functions from the libexcept are going to be included in your stack trace, using a very small depth such as 1 or 2 is not going to be helpful at all. You would only get data about the libexcept functions instead of the actual function that generated the error.

Definition at line 39 of file stack_trace.h.

This document is part of the Snap! Websites Project.

Copyright by Made to Order Software Corp.