12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
+ /**
16
+ * @file error_handling.h
17
+ * @brief Functions and macros to interact with error handling mechanisms
18
+ *
19
+ * This logic pretty much renames many `rcutils` functions and macros. Also check out that
20
+ * package's documentation for more information.
21
+ */
22
+
15
23
#ifndef RMW__ERROR_HANDLING_H_
16
24
#define RMW__ERROR_HANDLING_H_
17
25
@@ -22,33 +30,149 @@ extern "C"
22
30
23
31
#include <rcutils/error_handling.h>
24
32
33
+ /// Struct wrapping a fixed-size c string used for returning the formatted error string.
25
34
typedef rcutils_error_string_t rmw_error_string_t ;
35
+
36
+ /// Struct which encapsulates the error state set by RMW_SET_ERROR_MSG().
26
37
typedef rcutils_error_state_t rmw_error_state_t ;
27
38
39
+ /// Limit the buffer size in the `fwrite` call to give an upper bound to buffer overrun in the case
40
+ /// of non-null terminated `msg`.
28
41
#define RMW_SAFE_FWRITE_TO_STDERR RCUTILS_SAFE_FWRITE_TO_STDERR
29
42
43
+ /// Forces initialization of thread-local storage if called in a newly created thread.
44
+ /**
45
+ * If this function is not called beforehand, then the first time the error
46
+ * state is set or the first time the error message is retrieved, the default
47
+ * allocator will be used to allocate thread-local storage.
48
+ *
49
+ * This function may or may not allocate memory.
50
+ * The system's thread-local storage implementation may need to allocate
51
+ * memory, since it usually has no way of knowing how much storage is needed
52
+ * without knowing how many threads will be created.
53
+ * Most implementations (e.g. C11, C++11, and pthread) do not have ways to
54
+ * specify how this memory is allocated, but if the implementation allows, the
55
+ * given allocator to this function will be used, but is otherwise unused.
56
+ * This only occurs when creating and destroying threads, which can be avoided
57
+ * in the "steady" state by reusing pools of threads.
58
+ *
59
+ * It is worth considering that repeated thread creation and destruction will
60
+ * result in repeated memory allocations and could result in memory
61
+ * fragmentation.
62
+ * This is typically avoided anyways by using pools of threads.
63
+ *
64
+ * In case an error is indicated by the return code, no error message will have
65
+ * been set.
66
+ *
67
+ * If called more than once in a thread, or after implicitly initialized by
68
+ * setting the error state, it will still return `RCUTILS_RET_OK`, even
69
+ * if the given allocator is invalid.
70
+ * Essentially this function does nothing if thread-local storage has already
71
+ * been called.
72
+ * If already initialized, the given allocator is ignored, even if it does not
73
+ * match the allocator used originally to initialize the thread-local storage.
74
+ *
75
+ * \return `RCUTILS_RET_OK` if successful, or
76
+ * \return `RCUTILS_RET_INVALID_ARGUMENT` if the allocator is invalid, or
77
+ * \return `RCUTILS_RET_BAD_ALLOC` if allocating memory fails, or
78
+ * \return `RCUTILS_RET_ERROR` if an unspecified error occurs.
79
+ */
30
80
#define rmw_initialize_error_handling_thread_local_storage \
31
81
rcutils_initialize_error_handling_thread_local_storage
32
82
83
+ /// Set the error message, as well as the file and line on which it occurred.
84
+ /**
85
+ * This is not meant to be used directly, but instead via the
86
+ * RMW_SET_ERROR_MSG(msg) macro.
87
+ *
88
+ * The error_msg parameter is copied into the internal error storage and must
89
+ * be null terminated.
90
+ * The file parameter is copied into the internal error storage and must
91
+ * be null terminated.
92
+ *
93
+ * \param[in] error_string The error message to set.
94
+ * \param[in] file The path to the file in which the error occurred.
95
+ * \param[in] line_number The line number on which the error occurred.
96
+ */
33
97
#define rmw_set_error_state rcutils_set_error_state
34
98
99
+ /// Check an argument for a null value.
100
+ /**
101
+ * If the argument's value is `NULL`, set the error message saying so and
102
+ * return the `error_return_type`.
103
+ *
104
+ * \param[in] argument The argument to test.
105
+ * \param[in] error_return_type The type to return if the argument is `NULL`.
106
+ */
35
107
#define RMW_CHECK_ARGUMENT_FOR_NULL (argument , error_return_type ) \
36
108
RCUTILS_CHECK_ARGUMENT_FOR_NULL(argument, error_return_type)
37
109
110
+ /// Check a value for null, with an error message and error statement.
111
+ /**
112
+ * If `value` is `NULL`, the error statement will be evaluated after
113
+ * setting the error message.
114
+ *
115
+ * \param[in] value The value to test.
116
+ * \param[in] msg The error message if `value` is `NULL`.
117
+ * \param[in] error_statement The statement to evaluate if `value` is `NULL`.
118
+ */
38
119
#define RMW_CHECK_FOR_NULL_WITH_MSG (value , msg , error_statement ) \
39
120
RCUTILS_CHECK_FOR_NULL_WITH_MSG(value, msg, error_statement)
40
121
122
+ /// Set the error message, as well as append the current file and line number.
123
+ /**
124
+ * If an error message was previously set, and rmw_reset_error() was not called
125
+ * afterwards, and this library was built with RCUTILS_REPORT_ERROR_HANDLING_ERRORS
126
+ * turned on, then the previously set error message will be printed to stderr.
127
+ * Error state storage is thread local and so all error related functions are
128
+ * also thread local.
129
+ *
130
+ * \param[in] msg The error message to be set.
131
+ */
41
132
#define RMW_SET_ERROR_MSG (msg ) RCUTILS_SET_ERROR_MSG(msg)
42
133
134
+ /// Set the error message using a format string and format arguments.
135
+ /**
136
+ * This function sets the error message using the given format string.
137
+ * The resulting formatted string is silently truncated at
138
+ * RCUTILS_ERROR_MESSAGE_MAX_LENGTH.
139
+ *
140
+ * \param[in] format_string The string to be used as the format of the error message.
141
+ * \param[in] ... Arguments for the format string.
142
+ */
43
143
#define RMW_SET_ERROR_MSG_WITH_FORMAT_STRING (format_string , ...) \
44
144
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(format_string, __VA_ARGS__)
45
145
146
+ /// Return `true` if the error is set, otherwise `false`.
147
+ /**
148
+ * This is currently defines as `rcutils_error_is_set`
149
+ */
46
150
#define rmw_error_is_set rcutils_error_is_set
47
151
152
+ /// Return an rcutils_error_state_t which was set with rcutils_set_error_state().
153
+ /**
154
+ * The returned pointer will be NULL if no error has been set in this thread.
155
+ *
156
+ * The returned pointer is valid until RCUTILS_SET_ERROR_MSG, rcutils_set_error_state,
157
+ * or rcutils_reset_error are called in the same thread.
158
+ *
159
+ * \return A pointer to the current error state struct.
160
+ */
48
161
#define rmw_get_error_state rcutils_get_error_state
49
162
163
+ /// Return the error message followed by `, at <file>:<line>` if set, else "error not set".
164
+ /**
165
+ * This function is "safe" because it returns a copy of the current error
166
+ * string or one containing the string "error not set" if no error was set.
167
+ * This ensures that the copy is owned by the calling thread and is therefore
168
+ * never invalidated by other error handling calls, and that the C string
169
+ * inside is always valid and null terminated.
170
+ *
171
+ * \return The current error string, with file and line number, or "error not set" if not set.
172
+ */
50
173
#define rmw_get_error_string rcutils_get_error_string
51
174
175
+ /// Reset the error state by clearing any previously set error state.
52
176
#define rmw_reset_error rcutils_reset_error
53
177
54
178
#ifdef __cplusplus
0 commit comments