1 /*
2  *
3  * Copyright 2016 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPC_CORE_LIB_IOMGR_ERROR_H
20 #define GRPC_CORE_LIB_IOMGR_ERROR_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include <inttypes.h>
25 #include <stdbool.h>
26 
27 #include <grpc/slice.h>
28 #include <grpc/status.h>
29 #include <grpc/support/log.h>
30 #include <grpc/support/time.h>
31 
32 #include "src/core/lib/debug/trace.h"
33 #include "src/core/lib/gprpp/inlined_vector.h"
34 
35 /// Opaque representation of an error.
36 /// See https://github.com/grpc/grpc/blob/master/doc/core/grpc-error.md for a
37 /// full write up of this object.
38 
39 typedef struct grpc_error grpc_error;
40 
41 extern grpc_core::DebugOnlyTraceFlag grpc_trace_error_refcount;
42 
43 typedef enum {
44   /// 'errno' from the operating system
45   GRPC_ERROR_INT_ERRNO,
46   /// __LINE__ from the call site creating the error
47   GRPC_ERROR_INT_FILE_LINE,
48   /// stream identifier: for errors that are associated with an individual
49   /// wire stream
50   GRPC_ERROR_INT_STREAM_ID,
51   /// grpc status code representing this error
52   GRPC_ERROR_INT_GRPC_STATUS,
53   /// offset into some binary blob (usually represented by
54   /// GRPC_ERROR_STR_RAW_BYTES) where the error occurred
55   GRPC_ERROR_INT_OFFSET,
56   /// context sensitive index associated with the error
57   GRPC_ERROR_INT_INDEX,
58   /// context sensitive size associated with the error
59   GRPC_ERROR_INT_SIZE,
60   /// http2 error code associated with the error (see the HTTP2 RFC)
61   GRPC_ERROR_INT_HTTP2_ERROR,
62   /// TSI status code associated with the error
63   GRPC_ERROR_INT_TSI_CODE,
64   /// grpc_security_status associated with the error
65   GRPC_ERROR_INT_SECURITY_STATUS,
66   /// WSAGetLastError() reported when this error occurred
67   GRPC_ERROR_INT_WSA_ERROR,
68   /// File descriptor associated with this error
69   GRPC_ERROR_INT_FD,
70   /// HTTP status (i.e. 404)
71   GRPC_ERROR_INT_HTTP_STATUS,
72   /// context sensitive limit associated with the error
73   GRPC_ERROR_INT_LIMIT,
74   /// chttp2: did the error occur while a write was in progress
75   GRPC_ERROR_INT_OCCURRED_DURING_WRITE,
76 
77   /// Must always be last
78   GRPC_ERROR_INT_MAX,
79 } grpc_error_ints;
80 
81 typedef enum {
82   /// top-level textual description of this error
83   GRPC_ERROR_STR_DESCRIPTION,
84   /// source file in which this error occurred
85   GRPC_ERROR_STR_FILE,
86   /// operating system description of this error
87   GRPC_ERROR_STR_OS_ERROR,
88   /// syscall that generated this error
89   GRPC_ERROR_STR_SYSCALL,
90   /// peer that we were trying to communicate when this error occurred
91   GRPC_ERROR_STR_TARGET_ADDRESS,
92   /// grpc status message associated with this error
93   GRPC_ERROR_STR_GRPC_MESSAGE,
94   /// hex dump (or similar) with the data that generated this error
95   GRPC_ERROR_STR_RAW_BYTES,
96   /// tsi error string associated with this error
97   GRPC_ERROR_STR_TSI_ERROR,
98   /// filename that we were trying to read/write when this error occurred
99   GRPC_ERROR_STR_FILENAME,
100   /// which data was queued for writing when the error occurred
101   GRPC_ERROR_STR_QUEUED_BUFFERS,
102   /// key associated with the error
103   GRPC_ERROR_STR_KEY,
104   /// value associated with the error
105   GRPC_ERROR_STR_VALUE,
106 
107   /// Must always be last
108   GRPC_ERROR_STR_MAX,
109 } grpc_error_strs;
110 
111 typedef enum {
112   /// timestamp of error creation
113   GRPC_ERROR_TIME_CREATED,
114 
115   /// Must always be last
116   GRPC_ERROR_TIME_MAX,
117 } grpc_error_times;
118 
119 /// The following "special" errors can be propagated without allocating memory.
120 /// They are always even so that other code (particularly combiner locks,
121 /// polling engines) can safely use the lower bit for themselves.
122 
123 #define GRPC_ERROR_NONE ((grpc_error*)NULL)
124 #define GRPC_ERROR_RESERVED_1 ((grpc_error*)1)
125 #define GRPC_ERROR_OOM ((grpc_error*)2)
126 #define GRPC_ERROR_RESERVED_2 ((grpc_error*)3)
127 #define GRPC_ERROR_CANCELLED ((grpc_error*)4)
128 #define GRPC_ERROR_SPECIAL_MAX GRPC_ERROR_CANCELLED
129 
grpc_error_is_special(struct grpc_error * err)130 inline bool grpc_error_is_special(struct grpc_error* err) {
131   return err <= GRPC_ERROR_SPECIAL_MAX;
132 }
133 
134 // debug only toggles that allow for a sanity to check that ensures we will
135 // never create any errors in the per-RPC hotpath.
136 void grpc_disable_error_creation();
137 void grpc_enable_error_creation();
138 
139 const char* grpc_error_string(grpc_error* error);
140 
141 /// Create an error - but use GRPC_ERROR_CREATE instead
142 grpc_error* grpc_error_create(const char* file, int line,
143                               const grpc_slice& desc, grpc_error** referencing,
144                               size_t num_referencing);
145 /// Create an error (this is the preferred way of generating an error that is
146 ///   not due to a system call - for system calls, use GRPC_OS_ERROR or
147 ///   GRPC_WSA_ERROR as appropriate)
148 /// \a referencing is an array of num_referencing elements indicating one or
149 /// more errors that are believed to have contributed to this one
150 /// err = grpc_error_create(x, y, z, r, nr) is equivalent to:
151 ///   err = grpc_error_create(x, y, z, NULL, 0);
152 ///   for (i=0; i<nr; i++) err = grpc_error_add_child(err, r[i]);
153 #define GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc)                           \
154   grpc_error_create(__FILE__, __LINE__, grpc_slice_from_static_string(desc), \
155                     NULL, 0)
156 #define GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc)                           \
157   grpc_error_create(__FILE__, __LINE__, grpc_slice_from_copied_string(desc), \
158                     NULL, 0)
159 
160 // Create an error that references some other errors. This function adds a
161 // reference to each error in errs - it does not consume an existing reference
162 #define GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(desc, errs, count)  \
163   grpc_error_create(__FILE__, __LINE__, grpc_slice_from_static_string(desc), \
164                     errs, count)
165 #define GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(desc, errs, count)  \
166   grpc_error_create(__FILE__, __LINE__, grpc_slice_from_copied_string(desc), \
167                     errs, count)
168 
169 #define GRPC_ERROR_CREATE_FROM_VECTOR(desc, error_list) \
170   grpc_error_create_from_vector(__FILE__, __LINE__, desc, error_list)
171 
172 #ifndef NDEBUG
173 grpc_error* grpc_error_do_ref(grpc_error* err, const char* file, int line);
174 void grpc_error_do_unref(grpc_error* err, const char* file, int line);
grpc_error_ref(grpc_error * err,const char * file,int line)175 inline grpc_error* grpc_error_ref(grpc_error* err, const char* file, int line) {
176   if (grpc_error_is_special(err)) return err;
177   return grpc_error_do_ref(err, file, line);
178 }
grpc_error_unref(grpc_error * err,const char * file,int line)179 inline void grpc_error_unref(grpc_error* err, const char* file, int line) {
180   if (grpc_error_is_special(err)) return;
181   grpc_error_do_unref(err, file, line);
182 }
183 #define GRPC_ERROR_REF(err) grpc_error_ref(err, __FILE__, __LINE__)
184 #define GRPC_ERROR_UNREF(err) grpc_error_unref(err, __FILE__, __LINE__)
185 #else
186 grpc_error* grpc_error_do_ref(grpc_error* err);
187 void grpc_error_do_unref(grpc_error* err);
grpc_error_ref(grpc_error * err)188 inline grpc_error* grpc_error_ref(grpc_error* err) {
189   if (grpc_error_is_special(err)) return err;
190   return grpc_error_do_ref(err);
191 }
grpc_error_unref(grpc_error * err)192 inline void grpc_error_unref(grpc_error* err) {
193   if (grpc_error_is_special(err)) return;
194   grpc_error_do_unref(err);
195 }
196 #define GRPC_ERROR_REF(err) grpc_error_ref(err)
197 #define GRPC_ERROR_UNREF(err) grpc_error_unref(err)
198 #endif
199 
200 // Consumes all the errors in the vector and forms a referencing error from
201 // them. If the vector is empty, return GRPC_ERROR_NONE.
202 template <size_t N>
grpc_error_create_from_vector(const char * file,int line,const char * desc,grpc_core::InlinedVector<grpc_error *,N> * error_list)203 static grpc_error* grpc_error_create_from_vector(
204     const char* file, int line, const char* desc,
205     grpc_core::InlinedVector<grpc_error*, N>* error_list) {
206   grpc_error* error = GRPC_ERROR_NONE;
207   if (error_list->size() != 0) {
208     error = grpc_error_create(file, line, grpc_slice_from_static_string(desc),
209                               error_list->data(), error_list->size());
210     // Remove refs to all errors in error_list.
211     for (size_t i = 0; i < error_list->size(); i++) {
212       GRPC_ERROR_UNREF((*error_list)[i]);
213     }
214     error_list->clear();
215   }
216   return error;
217 }
218 
219 grpc_error* grpc_error_set_int(grpc_error* src, grpc_error_ints which,
220                                intptr_t value) GRPC_MUST_USE_RESULT;
221 /// It is an error to pass nullptr as `p`. Caller should allocate a dummy
222 /// intptr_t for `p`, even if the value of `p` is not used.
223 bool grpc_error_get_int(grpc_error* error, grpc_error_ints which, intptr_t* p);
224 /// This call takes ownership of the slice; the error is responsible for
225 /// eventually unref-ing it.
226 grpc_error* grpc_error_set_str(grpc_error* src, grpc_error_strs which,
227                                const grpc_slice& str) GRPC_MUST_USE_RESULT;
228 /// Returns false if the specified string is not set.
229 /// Caller does NOT own the slice.
230 bool grpc_error_get_str(grpc_error* error, grpc_error_strs which,
231                         grpc_slice* s);
232 
233 /// Add a child error: an error that is believed to have contributed to this
234 /// error occurring. Allows root causing high level errors from lower level
235 /// errors that contributed to them. The src error takes ownership of the
236 /// child error.
237 ///
238 /// Edge Conditions -
239 /// 1) If either of \a src or \a child is GRPC_ERROR_NONE, returns a reference
240 /// to the other argument. 2) If both \a src and \a child are GRPC_ERROR_NONE,
241 /// returns GRPC_ERROR_NONE. 3) If \a src and \a child point to the same error,
242 /// returns a single reference. (Note that, 2 references should have been
243 /// received to the error in this case.)
244 grpc_error* grpc_error_add_child(grpc_error* src,
245                                  grpc_error* child) GRPC_MUST_USE_RESULT;
246 
247 grpc_error* grpc_os_error(const char* file, int line, int err,
248                           const char* call_name) GRPC_MUST_USE_RESULT;
249 
grpc_assert_never_ok(grpc_error * error)250 inline grpc_error* grpc_assert_never_ok(grpc_error* error) {
251   GPR_ASSERT(error != GRPC_ERROR_NONE);
252   return error;
253 }
254 
255 /// create an error associated with errno!=0 (an 'operating system' error)
256 #define GRPC_OS_ERROR(err, call_name) \
257   grpc_assert_never_ok(grpc_os_error(__FILE__, __LINE__, err, call_name))
258 grpc_error* grpc_wsa_error(const char* file, int line, int err,
259                            const char* call_name) GRPC_MUST_USE_RESULT;
260 /// windows only: create an error associated with WSAGetLastError()!=0
261 #define GRPC_WSA_ERROR(err, call_name) \
262   grpc_wsa_error(__FILE__, __LINE__, err, call_name)
263 
264 bool grpc_log_error(const char* what, grpc_error* error, const char* file,
265                     int line);
grpc_log_if_error(const char * what,grpc_error * error,const char * file,int line)266 inline bool grpc_log_if_error(const char* what, grpc_error* error,
267                               const char* file, int line) {
268   return error == GRPC_ERROR_NONE ? true
269                                   : grpc_log_error(what, error, file, line);
270 }
271 
272 #define GRPC_LOG_IF_ERROR(what, error) \
273   (grpc_log_if_error((what), (error), __FILE__, __LINE__))
274 
275 #endif /* GRPC_CORE_LIB_IOMGR_ERROR_H */
276