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