rcutils  master
C API providing common utilities and data structures.
error_handling.h
Go to the documentation of this file.
1 // Copyright 2014 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Note: migrated from rmw/error_handling.h in 2017-04
16 
17 #ifndef RCUTILS__ERROR_HANDLING_H_
18 #define RCUTILS__ERROR_HANDLING_H_
19 
20 #ifdef __cplusplus
21 extern "C"
22 {
23 #endif
24 
25 #ifndef __STDC_WANT_LIB_EXT1__
26 #define __STDC_WANT_LIB_EXT1__ 1 // indicate we would like strnlen_s if available
27 #endif
28 #include <assert.h>
29 #include <stdbool.h>
30 #include <stddef.h>
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "rcutils/allocator.h"
37 #include "rcutils/macros.h"
38 #include "rcutils/snprintf.h"
42 
43 #ifdef __STDC_LIB_EXT1__
44 // Limit the buffer size in the `fwrite` call to give an upper bound to buffer overrun in the case
45 // of non-null terminated `msg`.
46 #define RCUTILS_SAFE_FWRITE_TO_STDERR(msg) \
47  do {fwrite(msg, sizeof(char), strnlen_s(msg, 4096), stderr);} while (0)
48 #else
49 #define RCUTILS_SAFE_FWRITE_TO_STDERR(msg) \
50  do {fwrite(msg, sizeof(char), strlen(msg), stderr);} while (0)
51 #endif
52 
53 // fixed constraints
54 #define RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH 20 // "18446744073709551615"
55 #define RCUTILS_ERROR_FORMATTING_CHARACTERS 6 // ', at ' + ':'
56 
57 // max formatted string length
58 #define RCUTILS_ERROR_MESSAGE_MAX_LENGTH 1024
59 
60 // adjustable max length for user defined error message
61 // remember "chained" errors will include previously specified file paths
62 // e.g. "some error, at /path/to/a.c:42, at /path/to/b.c:42"
63 #define RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH 768
64 // with RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH = 768, RCUTILS_ERROR_STATE_FILE_MAX_LENGTH == 229
65 #define RCUTILS_ERROR_STATE_FILE_MAX_LENGTH ( \
66  RCUTILS_ERROR_MESSAGE_MAX_LENGTH - \
67  RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH - \
68  RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH - \
69  RCUTILS_ERROR_FORMATTING_CHARACTERS - \
70  1)
71 
73 typedef struct rcutils_error_string_t
74 {
77 
79 typedef struct rcutils_error_state_t
80 {
87  uint64_t line_number;
89 
90 // make sure our math is right...
91 #if __STDC_VERSION__ >= 201112L
92 static_assert(
93  sizeof(rcutils_error_string_t) == (
98  1 /* null terminating character */),
99  "Maximum length calculations incorrect");
100 #endif
101 
103 
144 
146 
160 void
161 rcutils_set_error_state(const char * error_string, const char * file, size_t line_number);
162 
164 
171 #define RCUTILS_CHECK_ARGUMENT_FOR_NULL(argument, error_return_type) \
172  RCUTILS_CHECK_FOR_NULL_WITH_MSG( \
173  argument, #argument " argument is null", \
174  return error_return_type)
175 
177 
185 #define RCUTILS_CHECK_FOR_NULL_WITH_MSG(value, msg, error_statement) \
186  do { \
187  if (NULL == value) { \
188  RCUTILS_SET_ERROR_MSG(msg); \
189  error_statement; \
190  } \
191  } while (0)
192 
194 
203 #define RCUTILS_SET_ERROR_MSG(msg) \
204  do {rcutils_set_error_state(msg, __FILE__, __LINE__);} while (0)
205 
207 
215 #define RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(format_string, ...) \
216  do { \
217  char output_msg[RCUTILS_ERROR_MESSAGE_MAX_LENGTH]; \
218  int ret = rcutils_snprintf(output_msg, sizeof(output_msg), format_string, __VA_ARGS__); \
219  if (ret < 0) { \
220  RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to call snprintf for error message formatting\n"); \
221  } else { \
222  RCUTILS_SET_ERROR_MSG(output_msg); \
223  } \
224  } while (0)
225 
227 
237 #define RCUTILS_CAN_SET_MSG_AND_RETURN_WITH_ERROR_OF(error_return_value) \
238  RCUTILS_CAN_FAIL_WITH( \
239  { \
240  RCUTILS_SET_ERROR_MSG("Injecting " RCUTILS_STRINGIFY(error_return_value)); \
241  return error_return_value; \
242  })
243 
247 bool
249 
251 
261 const rcutils_error_state_t *
263 
265 
278 
281 void
282 rcutils_reset_error(void);
283 
284 #ifdef __cplusplus
285 }
286 #endif
287 
288 #endif // RCUTILS__ERROR_HANDLING_H_
rcutils_error_is_set
bool rcutils_error_is_set(void)
Return true if the error is set, otherwise false.
rcutils_error_state_t
struct rcutils_error_state_t rcutils_error_state_t
Struct which encapsulates the error state set by RCUTILS_SET_ERROR_MSG().
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().
RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH
#define RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH
Definition: error_handling.h:54
RCUTILS_ERROR_FORMATTING_CHARACTERS
#define RCUTILS_ERROR_FORMATTING_CHARACTERS
Definition: error_handling.h:55
macros.h
rcutils_error_string_t
Struct wrapping a fixed-size c string used for returning the formatted error string.
Definition: error_handling.h:73
snprintf.h
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".
rcutils_error_state_t::file
char file[RCUTILS_ERROR_STATE_FILE_MAX_LENGTH]
Definition: error_handling.h:85
rcutils_error_state_t::line_number
uint64_t line_number
Line number of error.
Definition: error_handling.h:87
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
Definition: error_handling.h:58
RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH
#define RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH
Definition: error_handling.h:63
rcutils_ret_t
int rcutils_ret_t
Definition: rcutils_ret.h:23
rcutils_error_string_t
struct rcutils_error_string_t rcutils_error_string_t
Struct wrapping a fixed-size c string used for returning the formatted error string.
RCUTILS_WARN_UNUSED
#define RCUTILS_WARN_UNUSED
Definition: macros.h:24
rcutils_ret.h
visibility_control.h
rcutils_allocator_t
Encapsulation of an allocator.
Definition: allocator.h:45
allocator.h
RCUTILS_PUBLIC
#define RCUTILS_PUBLIC
Definition: visibility_control.h:23
fault_injection.h
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.
rcutils_error_string_t::str
char str[RCUTILS_ERROR_MESSAGE_MAX_LENGTH]
Definition: error_handling.h:75
rcutils_error_state_t::message
char message[RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH]
User message storage, limited to RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH characters.
Definition: error_handling.h:82
rcutils_error_state_t
Struct which encapsulates the error state set by RCUTILS_SET_ERROR_MSG().
Definition: error_handling.h:79
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.
RCUTILS_ERROR_STATE_FILE_MAX_LENGTH
#define RCUTILS_ERROR_STATE_FILE_MAX_LENGTH
Definition: error_handling.h:65