rcutils  master
C API providing common utilities and data structures.
Classes | Macros | Typedefs | Functions
error_handling.h File Reference
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rcutils/allocator.h"
#include "rcutils/macros.h"
#include "rcutils/snprintf.h"
#include "rcutils/testing/fault_injection.h"
#include "rcutils/types/rcutils_ret.h"
#include "rcutils/visibility_control.h"
Include dependency graph for error_handling.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  rcutils_error_string_t
 Struct wrapping a fixed-size c string used for returning the formatted error string. More...
 
struct  rcutils_error_state_t
 Struct which encapsulates the error state set by RCUTILS_SET_ERROR_MSG(). More...
 

Macros

#define __STDC_WANT_LIB_EXT1__   1
 
#define RCUTILS_SAFE_FWRITE_TO_STDERR(msg)   do {fwrite(msg, sizeof(char), strlen(msg), stderr);} while (0)
 Write the given msg out to stderr. More...
 
#define RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING(format_string, ...)
 Set the error message to stderr using a format string and format arguments. More...
 
#define RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH   20
 The maximum length a formatted number is allowed to have. More...
 
#define RCUTILS_ERROR_FORMATTING_CHARACTERS   6
 The maximum number of formatting characters allowed. More...
 
#define RCUTILS_ERROR_MESSAGE_MAX_LENGTH   1024
 The maximum formatted string length. More...
 
#define RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH   768
 The maximum length for user defined error message. More...
 
#define RCUTILS_ERROR_STATE_FILE_MAX_LENGTH
 The calculated maximum length for the filename. More...
 
#define RCUTILS_CHECK_ARGUMENT_FOR_NULL(argument, error_return_type)
 Check an argument for a null value. More...
 
#define RCUTILS_CHECK_FOR_NULL_WITH_MSG(value, msg, error_statement)
 Check a value for null, with an error message and error statement. More...
 
#define RCUTILS_SET_ERROR_MSG(msg)   do {rcutils_set_error_state(msg, __FILE__, __LINE__);} while (0)
 Set the error message, as well as append the current file and line number. More...
 
#define RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(format_string, ...)
 Set the error message using a format string and format arguments. More...
 
#define RCUTILS_CAN_SET_MSG_AND_RETURN_WITH_ERROR_OF(error_return_value)
 Indicate that the function intends to set an error message and return an error value. More...
 

Typedefs

typedef struct rcutils_error_string_t rcutils_error_string_t
 Struct wrapping a fixed-size c string used for returning the formatted error string. More...
 
typedef struct rcutils_error_state_t rcutils_error_state_t
 Struct which encapsulates the error state set by RCUTILS_SET_ERROR_MSG(). More...
 

Functions

rcutils_ret_t rcutils_initialize_error_handling_thread_local_storage (rcutils_allocator_t allocator)
 Forces initialization of thread-local storage if called in a newly created thread. More...
 
void rcutils_set_error_state (const char *error_string, const char *file, size_t line_number)
 Set the error message, as well as the file and line on which it occurred. More...
 
bool rcutils_error_is_set (void)
 Return true if the error is set, otherwise false. More...
 
const rcutils_error_state_trcutils_get_error_state (void)
 Return an rcutils_error_state_t which was set with rcutils_set_error_state(). More...
 
rcutils_error_string_t rcutils_get_error_string (void)
 Return the error message followed by , at <file>:<line> if set, else "error not set". More...
 
void rcutils_reset_error (void)
 Reset the error state by clearing any previously set error state. More...
 

Macro Definition Documentation

◆ __STDC_WANT_LIB_EXT1__

#define __STDC_WANT_LIB_EXT1__   1

◆ RCUTILS_SAFE_FWRITE_TO_STDERR

#define RCUTILS_SAFE_FWRITE_TO_STDERR (   msg)    do {fwrite(msg, sizeof(char), strlen(msg), stderr);} while (0)

Write the given msg out to stderr.

◆ RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING

#define RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING (   format_string,
  ... 
)
Value:
do { \
int ret = rcutils_snprintf(output_msg, sizeof(output_msg), format_string, __VA_ARGS__); \
if (ret < 0) { \
RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to call snprintf for error message formatting\n"); \
} else { \
RCUTILS_SAFE_FWRITE_TO_STDERR(output_msg); \
} \
} while (0)

Set the error message to stderr using a format string and format arguments.

This function sets the error message to stderr using the given format string. The resulting formatted string is silently truncated at RCUTILS_ERROR_MESSAGE_MAX_LENGTH.

Parameters
[in]format_stringThe string to be used as the format of the error message.
[in]...Arguments for the format string.

◆ RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH

#define RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH   20

The maximum length a formatted number is allowed to have.

◆ RCUTILS_ERROR_FORMATTING_CHARACTERS

#define RCUTILS_ERROR_FORMATTING_CHARACTERS   6

The maximum number of formatting characters allowed.

◆ RCUTILS_ERROR_MESSAGE_MAX_LENGTH

#define RCUTILS_ERROR_MESSAGE_MAX_LENGTH   1024

The maximum formatted string length.

◆ RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH

#define RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH   768

The maximum length for user defined error message.

Remember that "chained" errors will include previously specified file paths e.g. "some error, at /path/to/a.c:42, at /path/to/b.c:42"

◆ RCUTILS_ERROR_STATE_FILE_MAX_LENGTH

#define RCUTILS_ERROR_STATE_FILE_MAX_LENGTH
Value:
( \
RCUTILS_ERROR_MESSAGE_MAX_LENGTH - \
RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH - \
RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH - \
RCUTILS_ERROR_FORMATTING_CHARACTERS - \
1)

The calculated maximum length for the filename.

With RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH = 768, RCUTILS_ERROR_STATE_FILE_MAX_LENGTH == 229

◆ RCUTILS_CHECK_ARGUMENT_FOR_NULL

#define RCUTILS_CHECK_ARGUMENT_FOR_NULL (   argument,
  error_return_type 
)
Value:
argument, #argument " argument is null", \
return error_return_type)

Check an argument for a null value.

If the argument's value is NULL, set the error message saying so and return the error_return_type.

Parameters
[in]argumentThe argument to test.
[in]error_return_typeThe type to return if the argument is NULL.

◆ RCUTILS_CHECK_FOR_NULL_WITH_MSG

#define RCUTILS_CHECK_FOR_NULL_WITH_MSG (   value,
  msg,
  error_statement 
)
Value:
do { \
if (NULL == value) { \
RCUTILS_SET_ERROR_MSG(msg); \
error_statement; \
} \
} while (0)

Check a value for null, with an error message and error statement.

If value is NULL, the error statement will be evaluated after setting the error message.

Parameters
[in]valueThe value to test.
[in]msgThe error message if value is NULL.
[in]error_statementThe statement to evaluate if value is NULL.

◆ RCUTILS_SET_ERROR_MSG

#define RCUTILS_SET_ERROR_MSG (   msg)    do {rcutils_set_error_state(msg, __FILE__, __LINE__);} while (0)

Set the error message, as well as append the current file and line number.

If an error message was previously set, and rcutils_reset_error() was not called afterwards, and this library was built with RCUTILS_REPORT_ERROR_HANDLING_ERRORS turned on, then the previously set error message will be printed to stderr. Error state storage is thread local and so all error related functions are also thread local.

Parameters
[in]msgThe error message to be set.

◆ RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING

#define RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING (   format_string,
  ... 
)
Value:
do { \
int ret = rcutils_snprintf(output_msg, sizeof(output_msg), format_string, __VA_ARGS__); \
if (ret < 0) { \
RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to call snprintf for error message formatting\n"); \
} else { \
RCUTILS_SET_ERROR_MSG(output_msg); \
} \
} while (0)

Set the error message using a format string and format arguments.

This function sets the error message using the given format string. The resulting formatted string is silently truncated at RCUTILS_ERROR_MESSAGE_MAX_LENGTH.

Parameters
[in]format_stringThe string to be used as the format of the error message.
[in]...Arguments for the format string.

◆ RCUTILS_CAN_SET_MSG_AND_RETURN_WITH_ERROR_OF

#define RCUTILS_CAN_SET_MSG_AND_RETURN_WITH_ERROR_OF (   error_return_value)
Value:
{ \
RCUTILS_SET_ERROR_MSG("Injecting " RCUTILS_STRINGIFY(error_return_value)); \
return error_return_value; \
})

Indicate that the function intends to set an error message and return an error value.

Indicating macro similar to RCUTILS_CAN_RETURN_WITH_ERROR_OF, that also sets an error message.

For now, this macro simply relies on RCUTILS_CAN_FAIL_WITH to set a generic error message and return the given error_return_value if fault injection is enabled.

Parameters
error_return_valuethe value returned as a result of a given error.

Typedef Documentation

◆ rcutils_error_string_t

Struct wrapping a fixed-size c string used for returning the formatted error string.

◆ rcutils_error_state_t

Struct which encapsulates the error state set by RCUTILS_SET_ERROR_MSG().

Function Documentation

◆ rcutils_initialize_error_handling_thread_local_storage()

rcutils_ret_t rcutils_initialize_error_handling_thread_local_storage ( rcutils_allocator_t  allocator)

Forces initialization of thread-local storage if called in a newly created thread.

If this function is not called beforehand, then the first time the error state is set or the first time the error message is retrieved, the default allocator will be used to allocate thread-local storage.

This function may or may not allocate memory. The system's thread-local storage implementation may need to allocate memory, since it usually has no way of knowing how much storage is needed without knowing how many threads will be created. Most implementations (e.g. C11, C++11, and pthread) do not have ways to specify how this memory is allocated, but if the implementation allows, the given allocator to this function will be used, but is otherwise unused. This only occurs when creating and destroying threads, which can be avoided in the "steady" state by reusing pools of threads.

It is worth considering that repeated thread creation and destruction will result in repeated memory allocations and could result in memory fragmentation. This is typically avoided anyways by using pools of threads.

In case an error is indicated by the return code, no error message will have been set.

If called more than once in a thread, or after implicitly initialized by setting the error state, it will still return RCUTILS_RET_OK, even if the given allocator is invalid. Essentially this function does nothing if thread-local storage has already been called. If already initialized, the given allocator is ignored, even if it does not match the allocator used originally to initialize the thread-local storage.

Parameters
[in]allocatorto be used to allocate and deallocate memory
Returns
RCUTILS_RET_OK if successful, or
RCUTILS_RET_INVALID_ARGUMENT if the allocator is invalid, or
RCUTILS_RET_BAD_ALLOC if allocating memory fails, or
RCUTILS_RET_ERROR if an unspecified error occurs.

◆ rcutils_set_error_state()

void rcutils_set_error_state ( const char *  error_string,
const char *  file,
size_t  line_number 
)

Set the error message, as well as the file and line on which it occurred.

This is not meant to be used directly, but instead via the RCUTILS_SET_ERROR_MSG(msg) macro.

The error_msg parameter is copied into the internal error storage and must be null terminated. The file parameter is copied into the internal error storage and must be null terminated.

Parameters
[in]error_stringThe error message to set.
[in]fileThe path to the file in which the error occurred.
[in]line_numberThe line number on which the error occurred.

◆ rcutils_error_is_set()

bool rcutils_error_is_set ( void  )

Return true if the error is set, otherwise false.

◆ rcutils_get_error_state()

const rcutils_error_state_t* rcutils_get_error_state ( void  )

Return an rcutils_error_state_t which was set with rcutils_set_error_state().

The returned pointer will be NULL if no error has been set in this thread.

The returned pointer is valid until RCUTILS_SET_ERROR_MSG, rcutils_set_error_state, or rcutils_reset_error are called in the same thread.

Returns
A pointer to the current error state struct.

◆ rcutils_get_error_string()

rcutils_error_string_t rcutils_get_error_string ( void  )

Return the error message followed by , at <file>:<line> if set, else "error not set".

This function is "safe" because it returns a copy of the current error string or one containing the string "error not set" if no error was set. This ensures that the copy is owned by the calling thread and is therefore never invalidated by other error handling calls, and that the C string inside is always valid and null terminated.

Returns
The current error string, with file and line number, or "error not set" if not set.

◆ rcutils_reset_error()

void rcutils_reset_error ( void  )

Reset the error state by clearing any previously set error state.

RCUTILS_ERROR_MESSAGE_MAX_LENGTH
#define RCUTILS_ERROR_MESSAGE_MAX_LENGTH
The maximum formatted string length.
Definition: error_handling.h:84
RCUTILS_CHECK_FOR_NULL_WITH_MSG
#define RCUTILS_CHECK_FOR_NULL_WITH_MSG(value, msg, error_statement)
Check a value for null, with an error message and error statement.
Definition: error_handling.h:218
RCUTILS_CAN_FAIL_WITH
#define RCUTILS_CAN_FAIL_WITH(failure_code)
Definition: macros.h:206
rcutils_snprintf
int rcutils_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Format a string.