• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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