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_SRC_CORE_LIB_IOMGR_ERROR_H
20 #define GRPC_SRC_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 "absl/status/status.h"
28
29 #include <grpc/slice.h>
30 #include <grpc/status.h>
31 #include <grpc/support/log.h>
32 #include <grpc/support/time.h>
33
34 #include "src/core/lib/debug/trace.h"
35 #include "src/core/lib/gpr/spinlock.h"
36 #include "src/core/lib/gprpp/crash.h"
37 #include "src/core/lib/gprpp/status_helper.h"
38 #include "src/core/lib/slice/slice_internal.h"
39
40 /// Opaque representation of an error.
41
42 typedef absl::Status grpc_error_handle;
43
44 #define GRPC_ERROR_CREATE(desc) \
45 StatusCreate(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, {})
46
47 absl::Status grpc_status_create(absl::StatusCode code, absl::string_view msg,
48 const grpc_core::DebugLocation& location,
49 size_t children_count, absl::Status* children);
50
51 // Create an error that references some other errors.
52 #define GRPC_ERROR_CREATE_REFERENCING(desc, errs, count) \
53 grpc_status_create(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, count, \
54 errs)
55
56 // Consumes all the errors in the vector and forms a referencing error from
57 // them. If the vector is empty, return absl::OkStatus().
58 template <typename VectorType>
grpc_status_create_from_vector(const grpc_core::DebugLocation & location,absl::string_view desc,VectorType * error_list)59 static absl::Status grpc_status_create_from_vector(
60 const grpc_core::DebugLocation& location, absl::string_view desc,
61 VectorType* error_list) {
62 absl::Status error;
63 if (error_list->size() != 0) {
64 error = grpc_status_create(absl::StatusCode::kUnknown, desc, location,
65 error_list->size(), error_list->data());
66 error_list->clear();
67 }
68 return error;
69 }
70
71 #define GRPC_ERROR_CREATE_FROM_VECTOR(desc, error_list) \
72 grpc_status_create_from_vector(DEBUG_LOCATION, desc, error_list)
73
74 absl::Status grpc_os_error(const grpc_core::DebugLocation& location, int err,
75 const char* call_name);
76
grpc_assert_never_ok(absl::Status error)77 inline absl::Status grpc_assert_never_ok(absl::Status error) {
78 GPR_ASSERT(!error.ok());
79 return error;
80 }
81
82 /// create an error associated with errno!=0 (an 'operating system' error)
83 #define GRPC_OS_ERROR(err, call_name) \
84 grpc_assert_never_ok(grpc_os_error(DEBUG_LOCATION, err, call_name))
85
86 absl::Status grpc_wsa_error(const grpc_core::DebugLocation& location, int err,
87 absl::string_view call_name);
88
89 /// windows only: create an error associated with WSAGetLastError()!=0
90 #define GRPC_WSA_ERROR(err, call_name) \
91 grpc_wsa_error(DEBUG_LOCATION, err, call_name)
92
93 grpc_error_handle grpc_error_set_int(grpc_error_handle src,
94 grpc_core::StatusIntProperty which,
95 intptr_t value);
96 /// It is an error to pass nullptr as `p`. Caller should allocate a phony
97 /// intptr_t for `p`, even if the value of `p` is not used.
98 bool grpc_error_get_int(grpc_error_handle error,
99 grpc_core::StatusIntProperty which, intptr_t* p);
100 grpc_error_handle grpc_error_set_str(grpc_error_handle src,
101 grpc_core::StatusStrProperty which,
102 absl::string_view str);
103 /// Returns false if the specified string is not set.
104 bool grpc_error_get_str(grpc_error_handle error,
105 grpc_core::StatusStrProperty which, std::string* str);
106
107 /// Add a child error: an error that is believed to have contributed to this
108 /// error occurring. Allows root causing high level errors from lower level
109 /// errors that contributed to them. The src error takes ownership of the
110 /// child error.
111 ///
112 /// Edge Conditions -
113 /// 1) If either of \a src or \a child is absl::OkStatus(), returns a reference
114 /// to the other argument. 2) If both \a src and \a child are absl::OkStatus(),
115 /// returns absl::OkStatus(). 3) If \a src and \a child point to the same error,
116 /// returns a single reference. (Note that, 2 references should have been
117 /// received to the error in this case.)
118 grpc_error_handle grpc_error_add_child(grpc_error_handle src,
119 grpc_error_handle child);
120
121 bool grpc_log_error(const char* what, grpc_error_handle error, const char* file,
122 int line);
grpc_log_if_error(const char * what,grpc_error_handle error,const char * file,int line)123 inline bool grpc_log_if_error(const char* what, grpc_error_handle error,
124 const char* file, int line) {
125 return error.ok() ? true : grpc_log_error(what, error, file, line);
126 }
127
128 #define GRPC_LOG_IF_ERROR(what, error) \
129 (grpc_log_if_error((what), (error), __FILE__, __LINE__))
130
131 /// Helper class to get & set grpc_error_handle in a thread-safe fashion.
132 /// This could be considered as atomic<grpc_error_handle>.
133 class AtomicError {
134 public:
135 AtomicError() = default;
AtomicError(grpc_error_handle error)136 explicit AtomicError(grpc_error_handle error) { error_ = error; }
137
138 AtomicError(const AtomicError&) = delete;
139 AtomicError& operator=(const AtomicError&) = delete;
140
141 /// returns get() == absl::OkStatus()
ok()142 bool ok() {
143 gpr_spinlock_lock(&lock_);
144 bool ret = error_.ok();
145 gpr_spinlock_unlock(&lock_);
146 return ret;
147 }
148
get()149 grpc_error_handle get() {
150 gpr_spinlock_lock(&lock_);
151 grpc_error_handle ret = error_;
152 gpr_spinlock_unlock(&lock_);
153 return ret;
154 }
155
set(grpc_error_handle error)156 void set(grpc_error_handle error) {
157 gpr_spinlock_lock(&lock_);
158 error_ = error;
159 gpr_spinlock_unlock(&lock_);
160 }
161
162 private:
163 grpc_error_handle error_;
164 gpr_spinlock lock_ = GPR_SPINLOCK_STATIC_INITIALIZER;
165 };
166
167 #endif // GRPC_SRC_CORE_LIB_IOMGR_ERROR_H
168