Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
pv_error_handling.h
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // 00008 // http://www.apache.org/licenses/LICENSE-2.0 00009 // 00010 // Unless required by applicable law or agreed to in writing, software 00011 // distributed under the License is distributed on an "AS IS" BASIS, 00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 // See the License for the specific language governing permissions and 00014 // limitations under the License. 00015 // ---------------------------------------------------------------------------- 00016 00017 #ifndef __PV_ERROR_HANDLING_H__ 00018 #define __PV_ERROR_HANDLING_H__ 00019 00020 00021 #ifdef __cplusplus 00022 extern "C" { 00023 #endif 00024 00025 #include <assert.h> 00026 #include <stdbool.h> 00027 00028 #include "pv_log.h" 00029 00030 00031 /** The following are macros to enable different error handling in development 00032 * environment and production environment: 00033 * On development environment, in oredr to speed up bug fixing we might want 00034 * to assert or disable CK services. On production we shall not halt since 00035 * we might get the whole device stuck. 00036 * The errors are devided into 2 categories: 00037 * 1. recoverable errors - like invalid parameter to API function 00038 * 2. non-recoverable errors - like allocation failures 00039 * default values for production is to not halt in any case, 00040 * for development the default is to halt in non-recovrable error only 00041 * since recoverable error may occure in negative tests 00042 */ 00043 #ifdef DEVELOPMENT_ENV 00044 #define HALT_ON_RECOVERABLE_ERRORS() 0 00045 #define HALT_ON_UNRECOVERABLE_ERRORS() 0 00046 #else //if PRODUCTION_ENV 00047 #define HALT_ON_RECOVERABLE_ERRORS() 0 00048 #define HALT_ON_UNRECOVERABLE_ERRORS() 0 00049 #endif 00050 00051 /** Set this to 1 to immediately assert when an unrecoverable error is 00052 * detected in PC environment. 00053 * While it can be nice to get an immediate assert, often seeing the 00054 * call trace is more useful - so the default is NOT to assert. 00055 */ 00056 #define ASSERT_IN_PC_ENV() 0 00057 00058 // Currently, this flag is defined in makefile errors.mk 00059 // Set this to 1 in order to completely ignore unrecoverable errors - 00060 // condition won't be checked, nothing would be printed. 00061 // This should only be used in situations where memory is very tight, 00062 // and would render debugging very complicated! 00063 //#define IGNORE_UNRECOVERABLE_ERRORS 0 00064 00065 00066 void pv_error_occured(void); 00067 bool pv_error_is_error_occured(void); 00068 00069 #if ((HALT_ON_RECOVERABLE_ERRORS()) || (HALT_ON_UNRECOVERABLE_ERRORS())) 00070 #define SA_PV_IS_PREV_ERROR_OCCURED() (pv_error_is_error_occured()) 00071 #else 00072 #define SA_PV_IS_PREV_ERROR_OCCURED() (false) 00073 #endif 00074 00075 00076 00077 #define _SA_PV_ERR_ASSERT_UPON_ERROR(cond, return_code, ...) {\ 00078 if (cond) { \ 00079 SA_PV_LOG_ERR_FUNC_EXIT(__VA_ARGS__);\ 00080 assert(!(cond));\ 00081 (void)return_code; /* Mention explicitly to fail compilation if return_code is not compilable. */ \ 00082 abort();\ 00083 }\ 00084 } 00085 00086 #define _SA_PV_ERR_ASSERT_UPON_ERROR_GOTO(cond, return_code_assignment, goto_label, ...) {\ 00087 if (cond) {\ 00088 SA_PV_LOG_ERR(__VA_ARGS__);\ 00089 assert(!(cond));\ 00090 abort();\ 00091 return_code_assignment; /* Mention explicitly to fail compilation if return_code_assignment is not compilable. */ \ 00092 goto goto_label;\ 00093 }\ 00094 } 00095 00096 #define _SA_PV_ERR_OCCURED_AND_RETURN_UPON_ERROR(cond, return_code, ...) {\ 00097 if (cond) {\ 00098 SA_PV_LOG_ERR_FUNC_EXIT(__VA_ARGS__); \ 00099 pv_error_occured();\ 00100 return return_code;\ 00101 }\ 00102 } 00103 00104 #define _SA_PV_RETURN_UPON_ERROR(level, cond, return_code, ...) {\ 00105 if (cond) {\ 00106 SA_PV_LOG_ ## level ## _FUNC_EXIT(__VA_ARGS__);\ 00107 return return_code;\ 00108 }\ 00109 } 00110 #define _SA_PV_ERR_OCCURED_AND_GOTO_UPON_ERROR(cond, return_code_assignment, goto_label, ...) {\ 00111 if (cond) {\ 00112 SA_PV_LOG_ERR(__VA_ARGS__);\ 00113 pv_error_occured();\ 00114 return_code_assignment;\ 00115 goto goto_label;\ 00116 }\ 00117 } 00118 00119 #define _SA_PV_GOTO_UPON_ERROR(level, cond, return_code_assignment, goto_label, ...) {\ 00120 if (cond) {\ 00121 SA_PV_LOG_ ## level(__VA_ARGS__); \ 00122 return_code_assignment;\ 00123 goto goto_label;\ 00124 }\ 00125 } 00126 00127 00128 /** For non-recoverable errors, if condition fails: 00129 * log error message 00130 * if in development and running on PC - assert 00131 * if in development but not PC - disable further processing with CK and return error code 00132 * if in case in production (default behavior), just return error code 00133 */ 00134 #if HALT_ON_UNRECOVERABLE_ERRORS() 00135 #if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV() 00136 #ifndef IGNORE_UNRECOVERABLE_ERRORS 00137 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00138 _SA_PV_ERR_ASSERT_UPON_ERROR((cond), (return_code), ##__VA_ARGS__) 00139 #else 00140 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00141 if (false && (cond)) {} /* Dummy use of the condition to avoid compiler warnings */ 00142 #endif 00143 #else 00144 #ifndef IGNORE_UNRECOVERABLE_ERRORS 00145 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00146 _SA_PV_ERR_OCCURED_AND_RETURN_UPON_ERROR((cond), (return_code), ##__VA_ARGS__) 00147 #else 00148 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00149 if (false && (cond)) {} /* Dummy use of the condition to avoid compiler warnings */ 00150 #endif 00151 #endif 00152 #else // HALT_ON_UNRECOVERABLE_ERRORS 00153 #ifndef IGNORE_UNRECOVERABLE_ERRORS 00154 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00155 _SA_PV_RETURN_UPON_ERROR(ERR, (cond), (return_code), ##__VA_ARGS__) 00156 #else 00157 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00158 if (false && (cond)) {} /* Dummy use of the condition to avoid compiler warnings */ 00159 #endif 00160 #endif // HALT_ON_UNRECOVERABLE_ERRORS 00161 00162 /** For non-recoverable errors, if condition fails: 00163 * log error message 00164 * if in development and running on PC - assert 00165 * if in development but not PC - disable further processing with CK and assign error code and goto label 00166 * if in case in production (default behavior), just assign error code and goto label 00167 */ 00168 #if HALT_ON_UNRECOVERABLE_ERRORS() 00169 #if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV() 00170 #ifndef IGNORE_UNRECOVERABLE_ERRORS 00171 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00172 _SA_PV_ERR_ASSERT_UPON_ERROR_GOTO((cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00173 #else 00174 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00175 if (false && (cond)) { /* Dummy use of the condition to avoid compiler warnings */ \ 00176 return_code_assignment; /* Dummy use of the assignment to avoid compiler warnings */ \ 00177 goto goto_label; /* Dummy use of the goto label to avoid compiler warnings. */ \ 00178 } 00179 #endif 00180 #else 00181 #ifndef IGNORE_UNRECOVERABLE_ERRORS 00182 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00183 _SA_PV_ERR_OCCURED_AND_GOTO_UPON_ERROR((cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00184 #else 00185 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00186 if (false && (cond)) { /* Dummy use of the condition to avoid compiler warnings */ \ 00187 return_code_assignment; /* Dummy use of the assignment to avoid compiler warnings */ \ 00188 goto goto_label; /* Dummy use of the goto label to avoid compiler warnings. */ \ 00189 } 00190 #endif 00191 #endif 00192 #else // HALT_ON_UNRECOVERABLE_ERRORS 00193 #ifndef IGNORE_UNRECOVERABLE_ERRORS 00194 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00195 _SA_PV_GOTO_UPON_ERROR(ERR, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00196 #else 00197 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00198 if (false && (cond)) { /* Dummy use of the condition to avoid compiler warnings */ \ 00199 return_code_assignment; /* Dummy use of the assignment to avoid compiler warnings */ \ 00200 goto goto_label; /* Dummy use of the goto label to avoid compiler warnings. */ \ 00201 } 00202 #endif 00203 #endif // HALT_ON_UNRECOVERABLE_ERRORS 00204 00205 00206 /** Recoverable errors handling 00207 * For recoverable errors, if condition fails: 00208 * log error message 00209 * if in development and running on PC - assert 00210 * if in development but not PC - disable further processing with CK and return error code 00211 * if in case in production (default behavior), just log and return error code 00212 * this is all only regarding errors. INFO, TRACE, etc. will not cause halt, will just log and return error code 00213 */ 00214 #if HALT_ON_RECOVERABLE_ERRORS() 00215 #if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV() 00216 #define SA_PV_ERR_RECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00217 _SA_PV_ERR_ASSERT_UPON_ERROR((cond), return_code, ##__VA_ARGS__) 00218 #else 00219 #define SA_PV_ERR_RECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00220 _SA_PV_ERR_OCCURED_AND_RETURN_UPON_ERROR((cond), (return_code), ##__VA_ARGS__) 00221 #endif 00222 #else // HALT_ON_RECOVERABLE_ERRORS 00223 #define SA_PV_ERR_RECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00224 _SA_PV_RETURN_UPON_ERROR(ERR, (cond), (return_code), ##__VA_ARGS__) 00225 00226 #define SA_PV_ERR_RECOVERABLE_RETURN(return_code, ...) \ 00227 SA_PV_LOG_ERR_FUNC_EXIT(__VA_ARGS__); \ 00228 return return_code; 00229 #endif // HALT_ON_RECOVERABLE_ERRORS 00230 00231 // if the condition is true: 00232 // Theses macros return with return_code and perform the exit function log (if the log level is appropriate). 00233 00234 // FIXME: This is partial solution, for critical level, also unrecoverable return should be treated and 00235 // the macros for different flags should be implemented (HALT_ON_RECOVERABLE_ERRORS etc.) 00236 #define SA_PV_CRITICAL_RECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00237 _SA_PV_RETURN_UPON_ERROR(CRITICAL, (cond), (return_code), ##__VA_ARGS__) 00238 // used in errors that are not critical (such as failure to read data from a socket - a retry is scheduled) 00239 #define SA_PV_WARN_RECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00240 _SA_PV_RETURN_UPON_ERROR(WARN, (cond), (return_code), ##__VA_ARGS__) 00241 // used in external APIs 00242 #define SA_PV_INFO_RECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00243 _SA_PV_RETURN_UPON_ERROR(INFO, (cond), (return_code), ##__VA_ARGS__) 00244 // used in internal APIs 00245 #define SA_PV_TRACE_RECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00246 _SA_PV_RETURN_UPON_ERROR(TRACE, (cond), (return_code), ##__VA_ARGS__) 00247 #define SA_PV_DATA_RECOVERABLE_RETURN_IF(cond, return_code, ...) \ 00248 _SA_PV_RETURN_UPON_ERROR(DATA, (cond), (return_code), ##__VA_ARGS__) 00249 00250 /** For recoverable errors, if condition fails: 00251 * log error message 00252 * if in development and running on PC - assert 00253 * if in development but not PC - disable further processing with CK and assign error code and goto label 00254 * if in case in production (default behavior), just log, assign error code and goto label 00255 * this is all only regarding errors. INFO, TRACE, etc. will not cause halt, will just log, assign error code and goto label 00256 */ 00257 #if HALT_ON_RECOVERABLE_ERRORS() 00258 #if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV() 00259 #define SA_PV_ERR_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00260 _SA_PV_ERR_ASSERT_UPON_ERROR_GOTO((cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00261 #else 00262 #define SA_PV_ERR_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00263 _SA_PV_ERR_OCCURED_AND_GOTO_UPON_ERROR((cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00264 #endif 00265 #else // HALT_ON_RECOVERABLE_ERRORS 00266 #define SA_PV_ERR_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00267 _SA_PV_GOTO_UPON_ERROR(ERR, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00268 #endif // HALT_ON_RECOVERABLE_ERRORS 00269 00270 // if the condition is true: 00271 // Theses macros jump to goto_label with return_code and perform log (if the log level is appropriate). 00272 00273 // FIXME: This is partial solution, for critical level, also unrecoverable goto should be treated and 00274 // the macros for differnet flags should be implemented (HALT_ON_RECOVERABLE_ERRORS etc.) 00275 #define SA_PV_CRITICAL_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00276 _SA_PV_GOTO_UPON_ERROR(CRITICAL, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00277 // used in errors that are not critical (such as failure to read data from a socket - a retry is scheduled) 00278 #define SA_PV_WARN_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00279 _SA_PV_GOTO_UPON_ERROR(WARN, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00280 // used in external APIs 00281 #define SA_PV_INFO_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00282 _SA_PV_GOTO_UPON_ERROR(INFO, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00283 // used in internal APIs 00284 #define SA_PV_TRACE_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00285 _SA_PV_GOTO_UPON_ERROR(TRACE, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00286 // used in functions that are called many times and we don't necessary want to see all its logging even in TRACE mode 00287 #define SA_PV_DATA_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \ 00288 _SA_PV_GOTO_UPON_ERROR(DATA, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__) 00289 00290 #ifdef __cplusplus 00291 } 00292 #endif 00293 00294 #endif // __PV_ERROR_HANDLING_H__ 00295
Generated on Tue Jul 12 2022 19:01:36 by 1.7.2